我一直在用Silverlight代码使用NUnit和Moq编写单元测试。我一直遇到的一个问题与DependencyObjects有关。
如果从DependencyObject派生任何东西,那么我无法在我的测试中实例化它。例如,MouseEventArgs派生自DependencyObject。如果我有代码接受这些args,我无法创建args有几个原因......其中一个原因是它是DependencyObject。
据我所知,DependencyObject的基础构造函数正在尝试使用一些不存在的静态,除非整个Silverlight系统已启动并运行。任何从DependencyObject派生的类的构造都会引发异常。长号。
我不使用Silverlight Unit Test Framework,因为它实际上不是单元测试并且需要UI。我需要进行真正的无头单元测试。
无论如何,我提出的最好的方法是包装这些对象并为它们提供类似ITimelineMarker
的接口,并为其提供扩展方法:timelineMarker.ToInterface()
。这很好用,我可以嘲笑它们......但我想知道:
有没有人想出更好的方法来处理Silverlight单元测试中的DepencencyObjects?
答案 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基础设施,因此可能有助于解决有问题的例外情况。