NUnit / Moq:我已经嘲笑了一个类但是真正的构造函数被执行了,为什么?

时间:2014-07-01 07:30:14

标签: c# wpf unit-testing nunit moq

我有一个大型的传统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

1 个答案:

答案 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,你会很高兴。