7

I'd like to be able to test a class initialises correctly using Moq:

class ClassToTest
{
    public ClassToTest()
    {
        Method1(@"C:\myfile.dat")
    }
 
    public virtual void Method1(string filename)
    {
        // mock this method
        File.Create(filename);
    }
}

I thought I'd be able to use the CallBase property to create a testable version of the class, then use .Setup() to ensure Method1() does not execute any code.

However, creating the Mock<ClassToTest>() doesn't call the constructor, and if it did it'd be too late to do the Setup()!

If this is impossible, what is the best way round the problem whilst ensuring that the constructor behaves correctly?

EDIT: To make it clearer, I've added a parameter to Method1() to take a filename and added some behaviour. The test I'd like to write would be a working version of the following:

[Test]
public void ClassToTest_ShouldCreateFileOnInitialisation()
{
    var mockClass = new Mock<ClassToTest>() { CallBase = true };
    mockClass.Setup(x => x.Method1(It.IsAny<string>());

    mockClass.Verify(x => x.Method1(@"C:\myfile.dat"));
}
g t
  • 7,287
  • 7
  • 50
  • 85
  • 5
    Before you go down this path, please look into your design practices. Calling a virtual method in a constructor is not recommended, as it can cause very subtle bugs which are hard to track. See http://stackoverflow.com/questions/448258/calling-virtual-method-in-base-class-constructor for details. – Erik van Brakel Sep 08 '10 at 12:49
  • What is it that Method1() is doing that you need to mock? – Ian Johnson Sep 08 '10 at 12:49
  • Don't call virtual methods in constructors if you can. If you can't, can you please paste your test? – Grzenio Sep 08 '10 at 13:49
  • I only declare the method virtual in order to mock it out later. If this is wrong then I'll have to use another method... I've added an example which may help clarify what I'm trying to do. – g t Sep 09 '10 at 00:49

1 Answers1

10

Way down inside of Moq.Mock (actually inside the CastleProxyFactory that Moq uses)

mockClass.Object

will call the constructor by way of Activator.CreateInstance()

So your test would look something like

[Test]
public void ClassToTest_ShouldCreateFileOnInitialisation()
{
    Mock<ClassToTest> mockClass = new Mock<ClassToTest>();
    mockClass.Setup(x => x.Method1(It.IsAny<string>());

    var o = mockClass.Object;

    mockClass.Verify(x => x.Method1(@"C:\myfile.dat"));
}
Matt Mills
  • 8,692
  • 6
  • 40
  • 64