Fixture.Customize 对比 Fixture.Register
Fixture.Customize vs Fixture.Register
请解释自定义和注册之间的功能差异,何时使用其中一个。下面的 TestCustomize
示例失败,TestRegister
通过。我希望自定义脚本能够正常工作。它用英语读给我:
"When generating an HttpClient, use a post processing lambda on it before providing the specimin".
但我得到的是一个带有 guid 的 http 地址,显然是由 AutoFixture 生成的。
[Fact]
public void TestCustomize()
{
var fixture = new Fixture();
fixture.Customize<HttpClient>(c =>
{
//c.OmitAutoProperties(); makes no difference
c.Do(x => x.BaseAddress = new Uri("http://myval"));
return c;
});
var client = fixture.Create<HttpClient>();
Assert.Equal("http://myval/", client.BaseAddress.ToString());
}
[Fact]
public void TestRegister()
{
var fixture = new Fixture();
fixture.Register(() => new HttpClient
{
BaseAddress = new Uri("http://myval")
});
var client = fixture.Create<HttpClient>();
Assert.Equal("http://myval/", client.BaseAddress.ToString());
}
这与 Customize
与 Register
无关。事实上,如果您查看 source code for Register
,您会发现它只是 Customize
.
的一种便捷方法
问题出在Do
的使用上。如果您查看 Do
的签名,您会发现它具有以下类型:
IPostprocessComposer<T> Do(Action<T> action)
请注意方法 return 是一个值。在函数式风格中,或者,如果你愿意,遵循 Command-Query Separation,该方法不会改变定义它的实例,而是 return 一个具有改变行为的新对象。
当一个人写:
c.Do(x => x.BaseAddress = new Uri("http://myval"));
一个人立即丢弃具有更改行为的 return 值。在 F# 或 Haskell 等语言中,如果您编写这样的代码,您会收到编译时通知,告诉您您将忽略函数调用的 return 值,但 C# 不会不要那样做。
无论如何,AutoFixture 的 API 都被设计成 fluent interfaces。目的是将方法调用链接在一起:
fixture.Customize<HttpClient>(c => c
.Without(x => x.BaseAddress)
.Do(x => x.BaseAddress = new Uri("http://myval")));
您仍然需要 Without
(或者,如果您愿意,OmitAutoProperties
)来关闭默认的自动 属性 行为,否则,BaseAddress
将是被自动 属性 功能覆盖。
本版本测试通过:
[Fact]
public void TestCustomize()
{
var fixture = new Fixture();
fixture.Customize<HttpClient>(c => c
.Without(x => x.BaseAddress)
.Do(x => x.BaseAddress = new Uri("http://myval")));
var client = fixture.Create<HttpClient>();
Assert.Equal("http://myval/", client.BaseAddress.ToString());
}
请解释自定义和注册之间的功能差异,何时使用其中一个。下面的 TestCustomize
示例失败,TestRegister
通过。我希望自定义脚本能够正常工作。它用英语读给我:
"When generating an HttpClient, use a post processing lambda on it before providing the specimin".
但我得到的是一个带有 guid 的 http 地址,显然是由 AutoFixture 生成的。
[Fact]
public void TestCustomize()
{
var fixture = new Fixture();
fixture.Customize<HttpClient>(c =>
{
//c.OmitAutoProperties(); makes no difference
c.Do(x => x.BaseAddress = new Uri("http://myval"));
return c;
});
var client = fixture.Create<HttpClient>();
Assert.Equal("http://myval/", client.BaseAddress.ToString());
}
[Fact]
public void TestRegister()
{
var fixture = new Fixture();
fixture.Register(() => new HttpClient
{
BaseAddress = new Uri("http://myval")
});
var client = fixture.Create<HttpClient>();
Assert.Equal("http://myval/", client.BaseAddress.ToString());
}
这与 Customize
与 Register
无关。事实上,如果您查看 source code for Register
,您会发现它只是 Customize
.
问题出在Do
的使用上。如果您查看 Do
的签名,您会发现它具有以下类型:
IPostprocessComposer<T> Do(Action<T> action)
请注意方法 return 是一个值。在函数式风格中,或者,如果你愿意,遵循 Command-Query Separation,该方法不会改变定义它的实例,而是 return 一个具有改变行为的新对象。
当一个人写:
c.Do(x => x.BaseAddress = new Uri("http://myval"));
一个人立即丢弃具有更改行为的 return 值。在 F# 或 Haskell 等语言中,如果您编写这样的代码,您会收到编译时通知,告诉您您将忽略函数调用的 return 值,但 C# 不会不要那样做。
无论如何,AutoFixture 的 API 都被设计成 fluent interfaces。目的是将方法调用链接在一起:
fixture.Customize<HttpClient>(c => c
.Without(x => x.BaseAddress)
.Do(x => x.BaseAddress = new Uri("http://myval")));
您仍然需要 Without
(或者,如果您愿意,OmitAutoProperties
)来关闭默认的自动 属性 行为,否则,BaseAddress
将是被自动 属性 功能覆盖。
本版本测试通过:
[Fact]
public void TestCustomize()
{
var fixture = new Fixture();
fixture.Customize<HttpClient>(c => c
.Without(x => x.BaseAddress)
.Do(x => x.BaseAddress = new Uri("http://myval")));
var client = fixture.Create<HttpClient>();
Assert.Equal("http://myval/", client.BaseAddress.ToString());
}