【发布时间】:2026-02-05 12:25:01
【问题描述】:
我正在使用 Autofixture 进行单元测试,并使用自动生成的数据。
为了测试一个简单的控制器端点(通过 Id 获取员工),我正在做类似的事情:
[Theory, AutoData]
public void GetEmployeeById_ValidId_ReturnsExpectedModel(
EmployeeModel expectedEmployee,
[Frozen] Mock<IEmployeeService> employeeServiceMock,
EmployeesController sut)
{
employeeServiceMock
.Setup(x => x.GetEmployeeById(42))
.Returns(expectedEmployee);
var actual = sut.GetEmployeeById(42);
actual.As<OkObjectResult>().Value.As<EmployeeModel>()
.Should().BeEquivalentTo(expectedEmployee);
}
还有控制器:
[HttpGet("{id:int}")]
public IActionResult GetEmployeeById(int id)
{
var employee = employeeService.GetEmployeeById(id);
if (employee == null)
return NotFound("Employee not found");
return Ok(employee);
}
在此单元测试中,expectedEmployee 是使用“随机”数据自动生成的。 sut(被测系统)配置为生成所有必需的依赖项(其中之一是IEmplyeeService)。
这个单元测试的问题是,如果我在从控制器返回之前更改了员工,测试仍然会通过(因为它引用的是同一个对象):
employee.SomeInternalModel.FooProperty = "Foo";
return Ok(employee);
所以,我认为上面的单元测试很糟糕。
要让单元测试在这种情况下失败,我需要传递一个单独的对象:EmployeeModel 的深拷贝:
employeeServiceMock
.Setup(x => x.GetEmployeeById(42))
.Returns(expectedEmployee.DeepCopy());
我没有时间和资源为我的所有模型编写深拷贝方法。
如何轻松自动生成相同的模型?我考虑过播种AutoFixture,但它似乎不支持此功能。
你有什么优雅的建议吗?
【问题讨论】:
-
如果您的模型是简单的 POCO,那么深层复制方法可以像使用 JSON.Net 的
public static T DeepCopyPoco<T>(this T item) => JsonConvert.DeserializeObject<T>(JsonConvert.SerializeObject(item));一样简单。
标签: c# unit-testing asp.net-core autofixture