问题
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