具有依赖项的对象的单元测试工厂方法
本文关键字:单元测试 工厂 方法 对象 依赖 | 更新日期: 2023-09-27 18:33:45
我是单元测试的新手。
出于可维护性原因,建议使用 Factory 方法创建待测试类的实例。
喜欢:
public class StringCalculatorTests
{
[Fact]
public void Add_EmptyString_ReturnZero()
{
var calculator = CreateCalculator();
int result = calculator.Add("");
result.Should().Be(0);
}
private static StringCalculator CreateCalculator()
{
//Some difficult object creation
var logger = Substitute.For<ILogger>();
var calculator = new StringCalculator(logger);
calculator.Initialize();
return calculator;
}
}
一切都很好:如果 API 发生变化 - 我将仅在一个地方更改 StringCalculator 的创建,而不是在每个测试中。
但是,如果我需要更改某些ILogger
方法的返回值怎么办.或者我会ILogger
不是作为存根而是作为模拟:
[Fact]
public void Add_EmptyString_LogAboutEmptyInput()
{
var loggerMock = Substitute.For<ILogger>();
var calculator = new StringCalculator(loggerMock);
calculator.Initialize();
calculator.Add("");
logger.Received("Empty input.");
}
现在我不能使用工厂方法,如果 API 有变化 - 我应该通过我的测试来改变它。
我想过属性注入 - 但例如,对于 ILogger 来说,它可能不是好的本地默认值。(我知道 - 我们通常对记录器有很好的默认值,但它可能是另一个依赖项(
我想到了工厂方法的可选参数。但它似乎有逻辑。这很简单,但仍然是逻辑。
有什么好的方法可以解决这个问题吗?或者它已经足够好了,当我们需要它时,只在课堂上创建实例是一种常见的情况?
您可以重载工厂方法以接受模拟记录器。
private static StringCalculator CreateCalculator(ILogger logger)
{
var calculator = new StringCalculator(logger);
calculator.Initialize();
return calculator;
}
然后,您可以在测试中创建模拟记录器(如果在多个测试中使用相同的模拟,则可能是记录器的单独工厂方法(
[Fact]
public void Add_EmptyString_LogAboutEmptyInput()
{
var loggerMock = //whatever code you need to set up your mock
var calculator = CreateCalculator(loggerMock);
calculator.Add("");
logger.Received("Empty input.");
}