ryeguy
ryeguy

Reputation: 66851

How can I mock a method on an object without a default constructor?

Using moq, if I try to mock a method directly on Foo, I get this: Invalid verify on a non-virtual (overridable in VB) member.

My alternative is to mock IFoo, which gets rid of the above problem, but then I can't construct it because Foo does not have a paramaterless constructor (Constructor arguments cannot be passed for interface mocks.). What can I do?

Upvotes: 8

Views: 6133

Answers (2)

Phil Sandler
Phil Sandler

Reputation: 28016

You should be able to mock IFoo without problem, and you would have no reason to pass arguments when you are mocking an interface. Your IFoo mock will be exactly that (a mock!), and will have no knowledge of Foo or any real implementation, so passing constructor arguments would not make sense.

Edit: I would add that mocking an interface if one exists is almost always preferable to mocking a concrete implemention. If you only have a concrete implementation, the fact that you want to mock it probably means it would be a good candidate for adding an interface.

Upvotes: 7

oxilumin
oxilumin

Reputation: 4833

Moq creates a proxy-object which requires that all your mocked methods are overridable and your class is not sealed. So you can mark your method as virtual.

The code below works fine:

public interface IFoo
{
    int Test(int myParameter);
    int TestInternal(int myParameter);
}

public class Foo : IFoo
{
    private int _someConstructorArgument;

    public Foo(int someConstructorArgument)
    {
        _someConstructorArgument = someConstructorArgument;
    }

    public virtual int Test(int myParameter)
    {
        return _someConstructorArgument + TestInternal(myParameter);
    }

    public virtual int TestInternal(int myParameter)
    {
        return myParameter;
    }
}

public class Program
{
    static void Main(string[] args)
    {
        var mock = new Mock<Foo>(MockBehavior.Loose, 50);

        mock.Setup(x => x.TestInternal(100))
            .Returns(200);

        mock.CallBase = true;

        Console.WriteLine(mock.Object.Test(100));
        Console.ReadLine();
    }
}

Upvotes: 0

Related Questions