2009-04-17 107 views
3

我一直在用我的Silverlight代码编写NUnit和Moq一段时间的单元测试。我一直遇到的一个问题与DependencyObjects有关。在Silverlight单元测试中处理DependencyObjects

如果有任何东西是从DependencyObject派生的,那么我不能在我的测试中实例化它。例如,MouseEventArgs派生自DependencyObject。如果我的代码使用了这些参数,我不能创建参数有几个原因......其中之一就是它是一个DependencyObject。

据我所知,DependencyObject的基本构造函数正试图使用​​一些不存在的静态,除非整个Silverlight系统启动并运行。任何派生自DependencyObject的类的构造都会引发异常。游民。

我不使用Silverlight Unit Test Framework,因为它实际上不是单元测试,需要一个UI。我运行需要真正的无头单元测试。

总而言之,我所想到的最好的方法是包装这些对象并为它们提供像ITimelineMarker这样的接口,并且我给它们扩展方法来实现它:timelineMarker.ToInterface()。这很好,我可以嘲笑他们......但我想知道:

有没有人想出了一个更好的方法来处理Silverlight的单元测试DepencencyObjects?

+0

“派生自DependencyObject的任何类的构造抛出异常” - 什么是异常类和错误消息? – 2009-05-08 12:22:04

回答

3

为什么你的应用程序逻辑直接与SilverLight事件和对象绑定?试图通过UI来测试应用程序逻辑的警告是众所周知的反模式,并已经让位于更有效地解决此问题的模式。

您的用户界面确实应该只关注用户界面事件并将任何处理传递给其他图层,然后在用户界面中测试的唯一东西就是图形响应(例如,当您单击按钮时,侧面),测试这种交互的唯一好方法就是实际进行点击。

也许对您的问题更合适的答案是,您需要重构代码以使用模式(如MVC,MVP或MVVM),以便您可以独立于UI层测试应用程序逻辑。

0

你看过TestDriven.NETs Silverlight NUnit Project吗? Link

+0

是的。这就是我们使用的。该问题发生在该设置中。 – 2009-04-23 23:38:01

0

我可以在抽象类中看到DependencyObject。

从犀牛无耻翻录嘲笑documentation,想象你有一个抽象类:

public abstract class MessageBase { 
    private List<User> _receivers = new List<User>(); 
    public void Send() { 
     //Some setup 
     DetermineReceivers(); 
     SendMessages(); 
    } 
    private void SendMessages() { 
     //Lots of logic 
    } 
    protected abstract void DetermineReceivers(); 
    protected void AddReceiver(Group g) { 
     //Lots of logic <---- Test this 
    } 
} 

,你要测试的指示的一部分。然后,你会创建一个假类,你可以嘲笑:

TestFixture 
public sealed class MessageBaseTester { 
public abstract class MockMessageMocker 
{ 
    public abstract List<Group> RecipientsGroups { get; set; } 
} 
private class MockMessage : MessageBase { 
    private MockMessageMocker _mock; 
    public MockMessage(MockMessageMocker mock) { 
     _mock = mock; 
    } 
    protected override void DetermineReceivers() { 
     if (_mock.RecipientsGroups != null) 
     foreach(Group g in _mock.RecipientsGroups) 
      base.AddReceiver(g); 
    } 
} 
} 

之后你的测试可以做到以下几点:

Test 
public void ShouldblablablaWhenBlabla() { 
    var SuThelper = mocks.Stub(); 
    var SuT = new MockMessage(SuThelper); 
    using (mocks.Record()) 
    { 
     Expect.Call(SuTHelper.RecipientsGroups).Return(
      new List<Group>{ new Group(...) }); 
    } 
    using (mocks.Playback()) 
    { 
     SuT.Send(); 
    } 
} 

上述解决方案拥有你的优势,你不需要修改您的原始代码。然而,你需要编写一些“额外”的代码才能工作。

+0

不幸的是,这不起作用。我需要替换的对象是派生自DependencyObject(例如MouseEventArgs),它们通常是密封的,构造函数是内部的:( – 2009-05-05 20:31:17

+0

对不起,但是我没有看到任何派生自DependencyObject的MSDN中的MouseEventArgs。请您提供一个链接? – drozzy 2009-05-05 20:41:13

+0

@drozzy:Doat!你说得对... MouseEventArgs不是从DependencyObject派生出来的,它确实遭受了类似的问题,尽管它是一个带有内部构造函数的密封类 Some better例子(关闭我的头顶)是System.Windows.Media.SolidColorBrush或System.Windows.Media.TimelineMarker。 此外,Rhino Mocks是否可以在Silverlight中工作?这只是一个小问题... Moq在SL和可以抽出抽象类,即使我用我从(System.Windows.Media.Brush)派生的类型来尝试它,我仍然可以得到外部在基础构造函数中。 – 2009-05-06 11:49:23