NUnit/Moq:我嘲笑了一个类,但是执行了真正的构造函数,为什么? [英] NUnit/Moq: I have mocked a class but real contructor is executed, why?

查看:67
本文介绍了NUnit/Moq:我嘲笑了一个类,但是执行了真正的构造函数,为什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个大型的旧WPF项目,现在我正在尝试使用NUnit(v.2.6.3)和Moq(v.4.2)进行单元测试,但是在模拟某些类时遇到了麻烦.特别是有一个从System.Windows.Forms.Integration.WindowsFormsHost派生的控件类,它在整个项目中都是必需的,并且具有很多外部依赖项,因此能够对其进行模拟非常重要.

I have a large legacy WPF project that I'm now trying to get unit tested with NUnit (v. 2.6.3) and Moq (v. 4.2), but I'm having trouble with mocking certain classes. There's one in particular, a control class derived from System.Windows.Forms.Integration.WindowsFormsHost, that's needed all over the project and has a lot of external dependencies, so it's very important to be able to mock it.

让我们调用该类Foo,这是测试用例:

Let's call that class Foo, and here's the test case:

[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时,我们直接进入了 concrete Foo的构造函数!我已经确认这确实是在调试器中发生的,而且,测试运行因未找到具体实现所依赖的DLL的错误而崩溃.

My problem is that for some weird reason, while evaluating parameter mockFoo.Object in the last line, we go straight inside the constructor of the concrete class Foo! I have confirmed that this really happens with debugger, and also, the test run crashes with an error of not finding the DLL's the concrete implementation depends on.

有什么想法会导致这种情况吗?据我了解,这里应该与具体的实现没有任何联系!

Any ideas what could be causing this? As far as I understand, there should be NO connection to the concrete implementation here!

提前感谢您的任何建议!

Thanks in advance for any advice!

-Seppo

推荐答案

有什么想法会导致这种情况吗?据我了解,这里应该没有具体的实现方法!

Any ideas what could be causing this? As far as I understand, there should be NO connection to the concrete implementation here!

Moq通过从具体实现(您的情况)或实现接口(典型的,更常见的情况)中派生来创建其对象( mocks ):

Moq creates its objects (mocks) by deriving from concrete implementation (your case) or implementing interface (typical, more common case):

// implement interface
var mock1 = new Mock<IService>();
// derive from ServiceImplementation
var mock2 = new Mock<ServiceImplementation>();

这是基础机制的工作方式-为了创建 mock ,Moq必须通过实现接口或从中派生动态创建代表该模拟的新类型基类.这意味着您的Foo构造函数应该并且被执行.这就是它的工作原理.

This is how underlying mechanisms work -- in order to create mock, Moq will have to dynamically create new type representing that mock, either by implementing interface or deriving from base class. Which means your Foo constructor should and is executed. This is how it works.

由于这是遗留代码类(Foo),所以我建议使用新的可模拟接口包装它,并使您的代码依赖于此接口:

Since this is legacy code class (Foo) I suggest wrapping it with new, mockable interface and make your code depend on this interface instead:

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,您会很方便.

Your new (non-legacy) code should depend on IFoo, not Foo and you'll be good to go.

这篇关于NUnit/Moq:我嘲笑了一个类,但是执行了真正的构造函数,为什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆