在测试方法中使用mock参数或实例参数有什么用?

时间:2012-11-07 10:29:16

标签: c# unit-testing mocking moq stub

在测试方法中传递object参数的最佳做法是什么? 在这种情况下使用什么?(模拟,存根或创建对象的实例并填充它)

例如:

[Test]
public void LoadContentsFor_ValidUser_ReturnsEmptyList()
{
    var user = new User {Id = 1, FirstName = "Test"};
    var contents = this.contentPresentationService.LoadContentsFor(user);
    Assert.IsTrue(contents.Count == 0);
}

或使用模拟:

[Test]
public void LoadContentsFor_ValidUser_ReturnsEmptyList()
{
    var user = new Mock<User>();
    user.Setup(x => x.Id).Returns(1);
    user.Setup(x => x.FirstName).Returns("Test");
    var contents = this.contentPresentationService.LoadContentsFor(user.Object);
    Assert.IsTrue(contents.Count == 0);
}

2 个答案:

答案 0 :(得分:1)

如果是这个简单的对象,我建议手动创建或使用一些构建工具,例如 AutoFixture {{3} } (这两个库旨在处理您所询问的确切问题):

// AutoFixture example
var fixture = new Fixture();
var user = fixture
    .Build<User>()
    .With(u => u.Id, 1)
    .With(u => u.FirstName, "John")
    .CreateAnynomous();

最重要的是,AutoFixture提供了许多有用的功能,例如

  • 自动生成属性数据
  • 跳过不需要的属性
  • 用automocks替换某些属性(给NBuilder看一下)

特征,模拟框架不提供,因为它们服务于不同的角色。当然没有任何事情发生如果你仍然继续使用模拟,但鉴于上述不同的目的,它可能会让你的代码的读者感到困惑。

答案 1 :(得分:1)

对于你的情况,我会在你的第一个例子中创建一个用户的具体对象。您不需要模拟它,因为它存在于被测代码的边界内。

任何存在于被测试代码边界之外且实现数据访问,服务,会话管理等的对象都应该有一个接口,以便它们不会紧密耦合。拥有这些接口可以轻松模拟这些区域,因此不会进行真实的数据操作。