处理Silverlight单元测试中的DependencyObjects

时间:2009-04-17 18:05:59

标签: silverlight unit-testing

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

如果从DependencyObject派生任何东西,那么我无法在我的测试中实例化它。例如,MouseEventArgs派生自DependencyObject。如果我有代码接受这些args,我无法创建args有几个原因......其中一个原因是它是DependencyObject。

据我所知,DependencyObject的基础构造函数正在尝试使用一些不存在的静态,除非整个Silverlight系统已启动并运行。任何从DependencyObject派生的类的构造都会引发异常。长号。

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

无论如何,我提出的最好的方法是包装这些对象并为它们提供类似ITimelineMarker的接口,并为其提供扩展方法:timelineMarker.ToInterface()。这很好用,我可以嘲笑它们......但我想知道:

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

4 个答案:

答案 0 :(得分:3)

为什么应用程序逻辑直接绑定到SilverLight事件和对象?尝试通过它的UI测试应用程序逻辑的注意事项是众所周知的反模式,并且已经让位于以更有效的方式解决此问题的模式。

您的UI实际上应该只关注UI事件并将任何处理传递到另一个层,然后在UI中进行测试的唯一事情就是图形响应(例如当您单击按钮时,面板从中滑入测试这样的交互的唯一好方法是实际点击。

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

答案 1 :(得分:0)

您是否看过TestDriven.NETs的Silverlight NUnit项目? Link

答案 2 :(得分: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();
    }
 }

上述解决方案优于您的解决方案,因为您无需修改​​原始代码。但是,您需要编写一些“额外”代码才能正常工作。

答案 3 :(得分:0)

尝试将SilverUnit用于unit testing Silverlight。由于它伪造了Silverlight基础设施,因此可能有助于解决有问题的例外情况。