【问题标题】:What to use mock parameter or instance parameter in test method?在测试方法中使用什么模拟参数或实例参数?
【发布时间】:2012-11-07 10:29:15
【问题描述】:

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

例如:

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

【问题讨论】:

    标签: c# unit-testing mocking moq stub


    【解决方案1】:

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

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

    除此之外,AutoFixture 还提供了更多有用的功能,例如

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

    模拟框架不提供的功能,因为它们服务于不同的角色。当然,如果您仍然继续使用模拟,什么都不会发生,但鉴于上述不同的目的,这可能会让您的代码读者感到困惑

    【讨论】:

      【解决方案2】:

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-01-19
        • 1970-01-01
        • 1970-01-01
        • 2021-07-09
        • 1970-01-01
        • 2019-09-05
        • 1970-01-01
        相关资源
        最近更新 更多