繁体   English   中英

使用Moq模拟抽象类

[英]Mock Abstract class using Moq

我有下面的抽象类和测试方法。 使用“最小起订量”,我得到以下错误:

我的抽象课程:

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

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

测试类别:

  [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(), ""));
    }

错误信息 :

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

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

出现此错误的原因是,您正在对对象的特定实例设置期望值:

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

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

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

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

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

除了依赖一个确切的实例(即避免比较两个引用),您还可以检查任何实例:

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

或者,最好是满足特定条件的实例(假设GetUserRequestObject()的属性Name设置为Bob

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

您的GetUserRequestObject()可能会返回2个不同的UserRequestObject对象实例。

确保使用相同的实例设置期望并通过调用对其进行验证。 (否则,在设置期望值时使用It.IsAny<UserRequestObject>

Moq会检查对您的对象的引用。 您应该验证并将设置方法中使用的对象传递给它:

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

另外,您可以检查传递给方法的任何对象:

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>(), ""));
}

非常简单-您所做的一切正确,但您的验证错误。

您正在创建一个新的用户提供程序,但尚未指定要创建的提供程序。

您需要使用它而不是空白:

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

由此,您需要在检查新用户时纠正您的verify语句:

mockUserProvider.Verify(u => u.CreateUser(It.IsAny<User>()));

这意味着您实际上是在检查是否已创建用户实体,而在您测试期望的结​​果之前。 就像按照这种方式测试某些东西一样-假设您要创建一件艺术品,然后对其进行计划和设置(模拟)。 但您尚不知道将要创建的内容-因此在验证中,您需要创建艺术品,并且需要验证该艺术品是某种艺术品,而不仅要验证该方法是否已运行,因为它会返回您未检查的内容。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM