1

I have a mock setup:

_mock.Setup( x => x.Method( It.IsAny<Model>(), It.IsAny<string>(), IsAny<int>()));

and verify with:

_mock.Verify(x => x.Method( It.Is<Model>( p=> p.IsPresent && p.Search.Equals("term")), It.IsAny<string>(), It.IsAny<int>()), Times.Once());

public Results GetResults( Model model, string s, int i)
{
     return _repo.Method(model, s, i);
}

During test the method is called twice. Once with Search == "rubbish" and once with Search=="term". Yet verify fails with the message it's being invoked 2 times.

I though using It.Is on the important parameter should give the correct 'Once'. Any ideas?

Craig
  • 517
  • 1
  • 9
  • 17
  • The verification for the specific parameter looks ok, however the number of arguments in the setup and verification don't match - is this the problem or a typo? – Lennart Stoop Sep 26 '18 at 17:06
  • thanks Lennart, typo. Fixed now. – Craig Sep 26 '18 at 17:13
  • @Craig are you able to show the method under test? – Nkosi Sep 26 '18 at 17:18
  • method added above – Craig Sep 26 '18 at 17:26
  • @Craig Include the test as a [mcve] that can be used to reproduce the problem. That way we can try to figure out the problem. – Nkosi Sep 26 '18 at 17:37
  • 1
    The `Setup` line is redundant and can be removed. The error from `Verify` is telling you that the method on that mock is not being called with the parameters described. But as Nkosi said, without an MCVE, it would be guesswork. With an MCVE it would be easier to diagnose. – Richardissimo Sep 26 '18 at 19:56
  • I created a test harness based on the existing code. Of course, the test harness worked as expected. The existing code is difficult to extract as is - hence the cut-down harness. But I'll start afresh today & see what's going on. I'll post my mistake when I find it. Thanks for your help. – Craig Sep 27 '18 at 07:18
  • re-read details regarding Setup call. I can see why its redundant. Thanks. There's a good answer here. https://stackoverflow.com/questions/3179672/mock-objects-setup-method-test-driven-development – Craig Sep 27 '18 at 07:26
  • If you like that, you may also be interested that widespread use of `It.IsAny` is weakening your tests. Take a look at [this question](https://stackoverflow.com/questions/49332471/mock-verify-invocation) (including the comments), then the non-accepted answer (which was originally accepted, including the comments), then the accepted answer. – Richardissimo Sep 28 '18 at 04:29

1 Answers1

1

Just tried to restore you case and get working example. Please take a look, may be it helps you to solve the issue:

[Test]
public void MoqCallTests()
{
    // Arrange
    var _mock = new Mock<IRepo>();
    // you setup call
    _mock.Setup(x => x.Method(It.IsAny<Model>(), It.IsAny<string>(), It.IsAny<int>()));
    var service = new Service(_mock.Object);

    // Act 
    // call method with 'rubbish'
    service.GetResults(new Model {IsPresent = true, Search = "rubbish"}, string.Empty, 0);
    // call method with 'term'
    service.GetResults(new Model {IsPresent = true, Search = "term" }, string.Empty, 0);

    // Assert
    // your varify call
    _mock.Verify(x => x.Method(It.Is<Model>(p => p.IsPresent && p.Search.Equals("term")), It.IsAny<string>(), It.IsAny<int>()), Times.Once());
}

public class Service
{
    private readonly IRepo _repo;

    public Service(IRepo repo)
    {
        _repo = repo;
    }

    // your method for tests
    public Results GetResults(Model model, string s, int i)
    {
        return _repo.Method(model, s, i);
    }
}

public interface IRepo
{
    Results Method(Model model, string s, int i);
}

public class Model
{
    public bool IsPresent { get; set; }

    public string Search { get; set; }
}

public class Results
{
}
KozhevnikovDmitry
  • 1,660
  • 12
  • 27
  • thanks, I created a similar cut down test harness and it worked as expected. Clearly there's something going on in my real setup that's causing the issue. I'll keep tracing. – Craig Sep 27 '18 at 07:16
  • 1
    @Craig I'm running into a similar issue and noticed that if the complex object that's passed in changes, the Verify call appears to be using that state of the object and not the object as it was passed into the method. In my case I was calling a function, changing the object, then calling the function again but the "Times" check can't differentiate. – Smeghead Sev Nov 16 '21 at 17:01