【问题标题】:Mocking HttpResponse.StatusCode with AutoFixture and Moq使用 AutoFixture 和 Moq 模拟 HttpResponse.StatusCode
【发布时间】:2016-01-29 14:03:46
【问题描述】:

我正在使用AutoFixture as an auto-mocking container 并想模拟HttpResponse,以便我可以验证是否已设置特定的StatusCode。但是,当我打电话给SetupSet 时,我得到了NotImplementedException

var response = _fixture.Freeze<Mock<HttpResponseBase>>();
response
    .SetupSet(x => x.StatusCode = It.IsAny<int>());

如果我只使用 HttpResponseBase 的新 Mock,我也不例外,但是我必须编写一个 FreezeMoq 扩展方法,如 Mark Seemann 的 Freezing mocks 博客文章中所述。

AutoFixture 的作用是什么,这意味着我无法在基类抛出 NotImplementedException 的虚拟属性上设置集合,但仅使用 Moq 时可以?

【问题讨论】:

    标签: c# unit-testing autofixture


    【解决方案1】:

    起订量就是这样,您可以在不使用 AutoFixture 的情况下重现该行为:

    [Fact]
    public void ReducedRepro()
    {
        var response = new Mock<HttpResponseBase>();
        response.CallBase = true;
        Assert.Throws<NotImplementedException>(() =>
            response.SetupSet(x => x.StatusCode = It.IsAny<int>()));
    }
    

    上述测试通过,证明在这种情况下,当您将 CallBase 设置为 true 时,Moq 会抛出 NotImplementedException,这正是 AutoMoq 所做的。

    在大多数情况下,将CallBase 设置为 true 是模拟基类的适当配置(它对接口没有影响),因为这意味着您可以相信模拟类仍然具有所有默认行为,除非您覆盖虚拟方法。这样做的好处是您不必为所有虚拟方法调用 Setup 方法,否则会导致脆弱的测试。

    然而,在这种情况下,它会导致失败,因为HttpResponseBase.StatusCode 是一个虚拟方法,它通过从 getter 和 setter 中抛出 NotImplementedException 来“实现”。这个设计决定是如何通过代码审查的,这让我无法理解。

    您可以使用SetupProperty 轻松解决它:

    [Fact]
    public void Workaround()
    {
        var fixture = new Fixture().Customize(new AutoMoqCustomization());
        var response = fixture.Freeze<Mock<HttpResponseBase>>();
        response.SetupProperty(x => x.StatusCode);
        response.Object.StatusCode = 42;
        Assert.Equal(42, response.Object.StatusCode);
    }
    

    此测试通过,证明您现在可以分配和读取 StatusCode 属性的值。

    【讨论】:

    • 感谢一百万马克! SetupPropertyCallBase 对我来说是新的,我现在了解了更多关于 Moq 和 AutoFixture 的知识;)
    猜你喜欢
    • 1970-01-01
    • 2014-01-24
    • 2020-02-18
    • 2017-07-25
    • 2016-12-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-14
    相关资源
    最近更新 更多