【发布时间】:2023-03-12 09:12:01
【问题描述】:
我刚刚开始在我的单元测试中使用 AutoFixture.AutoMoq,我发现它对于创建我不关心具体值的对象非常有帮助。毕竟,匿名对象的创建就是一切。
当我关心一个或多个构造函数参数时,我正在苦苦挣扎。取下面ExampleComponent:
public class ExampleComponent
{
public ExampleComponent(IService service, string someValue)
{
}
}
我想编写一个测试,为someValue 提供一个特定值,但让IService 由AutoFixture.AutoMoq 自动创建。
我知道如何在我的IFixture 上使用Freeze 来保持将被注入组件的已知值,但我不太明白如何提供一个已知值我自己的。
这是我最想做的事情:
[TestMethod]
public void Create_ExampleComponent_With_Known_SomeValue()
{
// create a fixture that supports automocking
IFixture fixture = new Fixture().Customize(new AutoMoqCustomization());
// supply a known value for someValue (this method doesn't exist)
string knownValue = fixture.Freeze<string>("My known value");
// create an ExampleComponent with my known value injected
// but without bothering about the IService parameter
ExampleComponent component = this.fixture.Create<ExampleComponent>();
// exercise component knowning it has my known value injected
...
}
我知道我可以通过直接调用构造函数来做到这一点,但这将不再是匿名对象创建。有没有办法像这样使用 AutoFixture.AutoMock 还是我需要将 DI 容器合并到我的测试中才能做我想做的事情?
编辑:
我最初的问题可能不那么抽象,所以这是我的具体情况。
我有一个ICache 接口,它具有通用的TryRead<T> 和Write<T> 方法:
public interface ICache
{
bool TryRead<T>(string key, out T value);
void Write<T>(string key, T value);
// other methods not shown...
}
我正在实现一个CookieCache,其中ITypeConverter 处理对象与字符串之间的转换,lifespan 用于设置cookie 的到期日期。
public class CookieCache : ICache
{
public CookieCache(ITypeConverter converter, TimeSpan lifespan)
{
// usual storing of parameters
}
public bool TryRead<T>(string key, out T result)
{
// read the cookie value as string and convert it to the target type
}
public void Write<T>(string key, T value)
{
// write the value to a cookie, converted to a string
// set the expiry date of the cookie using the lifespan
}
// other methods not shown...
}
因此,在为 cookie 的到期日期编写测试时,我关心的是寿命,而不是转换器。
【问题讨论】:
-
为什么要这样做?场景是什么? IME,像这样的场景在
ExampleComponent中往往闻起来像混合问题。 AutoFixture 不支持开箱即用是有原因的。 -
@MarkSeemann 您如何看待我在编辑问题中的场景?我不认为这可以解释为混合问题。
-
嗯,这对我来说很难说,因为我不明白你打算如何使用
lifespan。lifespan不需要和当前时间交互吗?一旦你开始思考诸如此类的问题,也许仍然会出现抽象。上次我做这样的事情时,我到达了一个 ILease 接口,这使得缓存逻辑更加灵活,因为我现在可以支持:Absolute Expiry、Sliding Window Expiry、LRU Expiry 和许多其他选项。 -
@MarkSeemann 我喜欢 ILease 的声音,当我说我的解决方案不能被解释为混合问题时,我认为我必须纠正。自从编辑问题以来,我在
CookieCache中添加了一个IDateTimeProvider依赖项,并通过将lifespan添加到当前日期来设置cookie 的到期日期。我现在意识到这确实是一个混合问题,尽管这种混合问题只需要一行代码!
标签: c# unit-testing autofixture automocking