NUnit/Moq: I have mocked a class but real contructor is executed, why?

橙三吉。 提交于 2020-01-16 01:53:49

问题


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.

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);
    }
}

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


回答1:


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

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>();

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.

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();
   }
}

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



来源:https://stackoverflow.com/questions/24504730/nunit-moq-i-have-mocked-a-class-but-real-contructor-is-executed-why

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!