kord
kord

Reputation: 1039

Mock Setup Exception for valid setup

I have the following classes structure:

public class MyObj
{
    public int Number;
}
public interface IService
{
    int ProcessInt(MyObj obj);
}
public class Service : IService
{
    public int ProcessInt(MyObj myObj)
    {
        return myObj.Number;
    }
}

and then the consumer class

public class Class1
{
    public void Run(IService s)
    {
        var obj = new MyObj {Number = 1};
        Console.WriteLine(s.ProcessInt(obj));
    }
}

and then the unit test

[TestFixture]
public class MyTest
{

    private readonly Mock<IService> _service = new Mock<IService>(MockBehavior.Strict);
    private readonly Class1 _sut = new Class1();

    [SetUp]
    public void SetUp()
    {
        var obj = new MyObj {Number = 1};
        _service.Setup(x => x.ProcessInt(obj)).Returns(1);
    }

    [Test]
    public void TestClass1()
    {
        _sut.Run(_service.Object);
    }
}

The problem I have is that when I run the unit test, I get "Moq.MockException : IService.ProcessInt(MoqStuff.MyObj) invocation failed with mock behavior Strict.All invocations on the mock must have a corresponding setup." which is weird since I have the setup for that input.

Is this an expected behavior of Moq framework? Is there any way I can fix that?

Thank you

Upvotes: 0

Views: 2822

Answers (1)

dotnetom
dotnetom

Reputation: 24901

You have this code in your SetUp method:

var obj = new MyObj {Number = 1};
_service.Setup(x => x.ProcessInt(obj)).Returns(1);

Here you set up expectation, that ProcessInt is called with this specific object obj.

However, in your method Run you create another object:

var obj = new MyObj {Number = 1};

Though property value is the same, this object is totally different from the one you created in your SetUp method. This is the reason why you get exception about missing setup.

What you can do instead is set up your service for any input parameter using It.IsAny:

[SetUp]
public void SetUp()
{
    _service.Setup(x => x.ProcessInt(It.IsAny<MyObj>())).Returns(1);
}

This setup will work for any parameter value.

Or if you want to match only based on some criteria, you can use It.Is:

[SetUp]
public void SetUp()
{
    // setup only for cases where obj.Number == 1
    _service
        .Setup(x => x.ProcessInt(It.Is<MyObj>(o => o.Number == 1 )))
        .Returns(1);

    // setup only for cases where obj.Number == 2
    _service
        .Setup(x => x.ProcessInt(It.Is<MyObj>(o => o.Number == 2 )))
        .Returns(2);
}

Upvotes: 5

Related Questions