Question

I'm new to Moq and learning.

I need to test that a method returns the value expected. I have put together a noddy example to explain my problem. This fails miserably with:

"ArgumentException: Expression is not a method invocation: c => (c.DoSomething("Jo", "Blog", 1) = "OK")"

Can you correct what I am doing wrong?

[TestFixtureAttribute, CategoryAttribute("Customer")]
public class Can_test_a_customer
{
    [TestAttribute]
    public void Can_do_something()
    {
        var customerMock = new Mock<ICustomer>();

        customerMock.Setup(c => c.DoSomething("Jo", "Blog", 1)).Returns("OK");

        customerMock.Verify(c => c.DoSomething("Jo", "Blog", 1)=="OK");
    }
}

public interface ICustomer
{
    string DoSomething(string name, string surname, int age);
}

public class Customer : ICustomer
{
    public string DoSomething(string name, string surname, int age)
    {
        return "OK";
    }
}

In a nutshell: if I wanted to test a method like the one above, and I know that I am expecting back an "OK", how would I write it using Moq?

Thanks for any suggestions.

Was it helpful?

Solution

  1. You need a test subject that interacts with mock objects (unless you're writing a learner test for Moq.) I wrote up a simple one below
  2. You setup expectations on the mock object, specifying the exact arguments (strict - if you wish to ofcourse, else use Is.Any<string> to accept any string) and specify return values if any
  3. Your test subject (as part of the Act step of the test) will call onto your mock
  4. You assert the test subject behaved as required. The return value from the mock methods will be used by the test subject - verify it via the test subject's public interface.
  5. You also verify that all expectations that you specified were met - all methods that you expected to be called were in fact called.

.

[TestFixture]
public class Can_test_a_customer
{
  [Test]
  public void Can_do_something()
  {
    //arrange
    var customerMock = new Moq.Mock<ICustomer>();
    customerMock.Setup(c => c.DoSomething( Moq.It.Is<string>(name => name == "Jo"),
         Moq.It.Is<string>(surname => surname == "Blog"),
         Moq.It.Is<int>(age => age == 1)))
       .Returns("OK");

    //act
    var result = TestSubject.QueryCustomer(customerMock.Object);

    //assert
    Assert.AreEqual("OK", result, "Should have got an 'OK' from the customer");
    customerMock.VerifyAll();
  }
}

class TestSubject
{
  public static string QueryCustomer(ICustomer customer)
  {
    return customer.DoSomething("Jo", "Blog", 1);
  }
}

OTHER TIPS

Mock<T>.Verify doesn't return the value that the method call returned, so you can't just compare it to the expected value using "==".

In fact, there is no overload of Verify that returns anything, because you should never need to verify that a mocked method returns a specific value. After all, you were responsible for setting it up to return that value in the first place! Return values of mocked methods are there to be used by the code you're testing - you're not testing the mocks.

Use Verify to confirm that the method was called with the arguments you expected, or that a property was assigned a value you expected. The return values of mocked methods and properties aren't important by the time you get to the "assert" phase of your test.

You are doing the same thing this guy was doing here: How to Verify another method in the class was called using Moq

You are mocking what you are testing. This doesn't make sense. Use of Mocks is for isolation. Your Can_Do_Something test will always pass. No matter what. This is not a good test.

Take a closer look at Gishu's test or the test I proposed in the linked SO question.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top