Moq: Specifying return values as part of expectations

孤人 提交于 2019-12-03 15:26:13

问题


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.


回答1:


  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);
  }
}



回答2:


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.




回答3:


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.



来源:https://stackoverflow.com/questions/1436757/moq-specifying-return-values-as-part-of-expectations

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!