Mock Abstract class using Moq

I have the below abstract class and test method. Using "Moq" i got the below error:

My Abstact class :

   public abstract class UserProvider
{ 
    public abstract UserResponseObject CreateUser(UserRequestObject request, string userUrl);

    public abstract bool IsUserExist(UserRequestObject request, string userUrl);
}

Test Class :

  [TestMethod()]
    public void CreateUserTest()
    {
        var mockUserProvider = new Mock<UserProvider>(MockBehavior.Loose);

    //GetUserRequestObject is local method to set data

         mockUserProvider.
            Setup(u => u.CreateUser(GetUserRequestObject(), ""))
            .Returns(new UserResponseObject { uid = "123", uri = userUri }).Verifiable();

         var userProvider = mockUserProvider.Object.CreateUser(GetUserRequestObject(), "");

         mockUserProvider.Verify(u => u.CreateUser(GetUserRequestObject(), ""));
    }

Error Message :

Moq.MockException: Expected invocation on the mock at least once, but was never performed: u => u.CreateUser(.GetUserRequestObject(), "")

Anyone please explain, why i got this message and how to resolve it?


The reason why you are getting this error, is because you are setting the expectation on a specific instance of an object:

mockUserProvider.Verify(u => u.CreateUser(GetUserRequestObject(), ""));

This will depend heavily on how the method is implemented. eg This implementation of GetUserRequestObject() will create a new instance on each call, and the verify will always fail:

  private UserRequestObject GetUserRequestObject()
  {
     return new UserRequestObject();
  }

Whereas returning the same instance for the setup and verify will succeed:

  private UserRequestObject u = new UserRequestObject();
  private UserRequestObject GetUserRequestObject()
  {
     return u;
  }

Instead of being dependent on an exact instance (ie avoid comparing 2 references), you could instead either check for Any instance:

mockUserProvider.Verify(u => u.CreateUser(It.IsAny<UserRequestObject>(),
                        It.IsAny<string>()), Times.Once);

Or preferably, an instance which meets a specific criterion (Assuming that GetUserRequestObject() has a property Name which is set to Bob )

mockUserProvider.Verify(u => u.CreateUser(
                        It.Is<UserRequestObject>(x => x.Name == "Bob"),
                        It.Is<string>(s => s == "")));

Your GetUserRequestObject() might be returning 2 different instances of the UserRequestObject object.

Ensure the same instance is used for both setting the expectations and verifying it via the call. (else, use It.IsAny<UserRequestObject> while setting expectations.


Moq checks the reference to your object. You should verify and pass to it the same object that you used in setup method:

public void CreateUserTest()
{
    var mockUserProvider = new Mock<UserProvider>(MockBehavior.Loose);

//GetUserRequestObject is local method to set data
     var user = GetUserRequestObject();

     mockUserProvider.
        Setup(u => u.CreateUser(user, ""))
        .Returns(new UserResponseObject { uid = "123", uri = userUri }).Verifiable();

     var userProvider = mockUserProvider.Object.CreateUser(user, "");

     mockUserProvider.Verify(u => u.CreateUser(user, ""));
}

Alternatively you may check it for any object passed to method:

public void CreateUserTest()
{
    var mockUserProvider = new Mock<UserProvider>(MockBehavior.Loose);

//GetUserRequestObject is local method to set data

     mockUserProvider.
        Setup(u => u.CreateUser(Is.Any<User>(), ""))
        .Returns(new UserResponseObject { uid = "123", uri = userUri }).Verifiable();

     var userProvider = mockUserProvider.Object.CreateUser(Is.Any<User>(), "");

     mockUserProvider.Verify(u => u.CreateUser(Is.Any<User>(), ""));
}
链接地址: http://www.djcxy.com/p/54064.html

上一篇: 模拟与Moq的懒惰界面

下一篇: 模拟使用Moq的抽象类