tags:

views:

361

answers:

4

Hi,

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.

+4  A: 

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.

Matt Hamilton
+3  A: 
  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);
  }
}
Gishu
Exactly. His test has no test subject, which has lead to the confusion. You test a test subject, not a mock.
Anderson Imes
A: 

Fantastic answers guys. I will take it from there. Sort of all clear

Thanks

brix
A: 

You are doing the same thing this guy was doing here: http://stackoverflow.com/questions/1417048/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.

Anderson Imes
Hi,you are absolutely right ,I am new in the world of mocking So is it correct to say that Mocking a method is just to verify that the method was called or a property was set not to verify what the method returns.Is this correct?
jo
A mock is designed to verify an external method AND isolate the code you are *actually* testing. For example, if your class tried to access a database, you would mock your data acccess class so that not only did it return consistent results, but so your test didn't require a database to run. You are isolating the class you are testing from other changes to other classes you might make.
Anderson Imes