使用 AutoFixture 和 Moq 模拟 HttpResponse.StatusCode
Mocking HttpResponse.StatusCode with AutoFixture and Moq
我正在使用 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 博客中所述post.
AutoFixture 在做什么,这意味着我无法在虚拟 属性 上设置一个集合,其中基础 class 会抛出一个 NotImplementedException
,但是当仅使用 Moq 时可以吗?
Moq 就是这样,您可以在没有 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[=34] =] 确实如此。
在大多数情况下,将 CallBase
设置为 true 是模拟基础 classes 的适当配置(它对接口没有影响),因为这意味着您可以相信模拟的 class 仍然具有所有默认行为,除非您覆盖虚拟方法。这样做的好处是您不必为所有虚拟方法调用 Setup
方法,否则会导致脆弱的测试。
然而,在这种情况下,它会导致失败,因为 HttpResponseBase.StatusCode
是一个虚拟方法,它是 'implemented' 通过从 getter 和 [ 中抛出 NotImplementedException
=38=]。我无法理解该设计决策如何通过代码审查。
您可以使用 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
属性.
的值
我正在使用 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 博客中所述post.
AutoFixture 在做什么,这意味着我无法在虚拟 属性 上设置一个集合,其中基础 class 会抛出一个 NotImplementedException
,但是当仅使用 Moq 时可以吗?
Moq 就是这样,您可以在没有 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[=34] =] 确实如此。
在大多数情况下,将 CallBase
设置为 true 是模拟基础 classes 的适当配置(它对接口没有影响),因为这意味着您可以相信模拟的 class 仍然具有所有默认行为,除非您覆盖虚拟方法。这样做的好处是您不必为所有虚拟方法调用 Setup
方法,否则会导致脆弱的测试。
然而,在这种情况下,它会导致失败,因为 HttpResponseBase.StatusCode
是一个虚拟方法,它是 'implemented' 通过从 getter 和 [ 中抛出 NotImplementedException
=38=]。我无法理解该设计决策如何通过代码审查。
您可以使用 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
属性.