我有一个大型的传统WPF项目,我现在正在尝试使用NUnit(v.2.6.3)和Moq(v.4.2)进行单元测试,但我在模拟某些方面遇到了麻烦类。特别是一个,一个派生自System.Windows.Forms.Integration.WindowsFormsHost
的控件类,它需要整个项目并且有很多外部依赖关系,所以能够做到这一点非常重要嘲笑它。
让我们称之为Foo
课,这是测试用例:
[TestFixture,RequiresSTA]
public class TestMainWindowViewModel {
[Test]
public void Test1() {
var mockRepository = new MockRepository(MockBehavior.Loose) { DefaultValue = DefaultValue.Empty };
var mockFoo = mockRepository.Create<Foo>();
var sut = new MainWindowViewModel(mockFoo.Object);
}
}
我的问题是,出于一些奇怪的原因,在最后一行评估参数mockFoo.Object
时,我们直接进入具体类Foo
的构造函数!我已经确认调试器确实会发生这种情况,并且测试运行崩溃时会发现错误,即找不到具体实现取决于DLL的错误。
任何可能导致这种情况的想法?据我了解,这里的具体实现应该没有任何联系!
提前感谢任何建议!
-Seppo
答案 0 :(得分:1)
任何可能导致这种情况的想法?据我了解,这里的具体实现应该没有任何联系!
Moq通过派生从具体实现(您的案例)或实现界面(典型的,更常见的情况)创建其对象( mocks ):
// implement interface
var mock1 = new Mock<IService>();
// derive from ServiceImplementation
var mock2 = new Mock<ServiceImplementation>();
这就是底层机制的工作原理 - 为了创建 mock ,Moq将必须动态创建表示该模拟的新类型,或者通过实现接口或从中派生基类。这意味着您的Foo
构造函数应该执行。这是它的工作原理。
由于这是遗留代码类(Foo
),我建议使用新的可模拟接口将其包装起来,并使代码依赖于此接口:
interface IFoo
{
void DoFoo();
}
class FooWrapper : IFoo
{
private readonly Foo legacyFoo;
public FooWrapper(Foo legacyFoo)
{
this.legacyFoo = legacyFoo;
}
public void DoFoo()
{
legacyFoo.DoFoo();
}
}
你的新(非传统)代码应该依赖于IFoo,而不是Foo,你会很高兴。