使用Moq模拟抽象类

Ven*_*kat 1 c# unit-testing moq

我有以下抽象类和测试方法.使用"Moq"我得到以下错误:

我的Abstact课程:

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

    public abstract bool IsUserExist(UserRequestObject request, string userUrl);
}
Run Code Online (Sandbox Code Playgroud)

测试类:

  [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(), ""));
    }
Run Code Online (Sandbox Code Playgroud)

错误信息 :

Moq.MockException:模拟上的预期调用至少一次,但从未执行过:u => u.CreateUser(.GetUserRequestObject(),"")

有人请解释一下,为什么我收到这条消息以及如何解决?

Stu*_*tLC 5

您收到此错误的原因是因为您正在设置对象的特定实例的期望:

mockUserProvider.Verify(u => u.CreateUser(GetUserRequestObject(), ""));
Run Code Online (Sandbox Code Playgroud)

这在很大程度上取决于方法的实现方式.例如,此实现GetUserRequestObject()将在每次调用时创建一个新实例,并且验证将始终失败:

  private UserRequestObject GetUserRequestObject()
  {
     return new UserRequestObject();
  }
Run Code Online (Sandbox Code Playgroud)

而为设置和验证返回相同的实例将成功:

  private UserRequestObject u = new UserRequestObject();
  private UserRequestObject GetUserRequestObject()
  {
     return u;
  }
Run Code Online (Sandbox Code Playgroud)

您可以改为检查Any实例,而不是依赖于确切的实例(即避免比较2个引用).

mockUserProvider.Verify(u => u.CreateUser(It.IsAny<UserRequestObject>(),
                        It.IsAny<string>()), Times.Once);
Run Code Online (Sandbox Code Playgroud)

或者最好是满足特定标准的实例(假设GetUserRequestObject()具有Name设置的属性Bob)

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