问题描述
我的 xunit 测试失败,因为在单元测试时数据库没有更新预期的 Id。 如何模拟数据库创建的 id/主键?
[HttpPost]
public async Task<ActionResult<AccountReadDto>> CreateAccountAsync(AccountCreateDto createAccountDto)
{
var account = _mapper.Map<Account>(createAccountDto); // Id is int equal to 0
await _accountRepo.CreateAccountAsync(account); // repo calls db and updates Id with pk
_accountRepo.SaveChanges();
var accountReadDto = _mapper.Map<AccountReadDto>(account);
return CreatedAtRoute(nameof(GetAccountByIdAsync),new { AccountId = accountReadDto.AccountId },accountReadDto);
}
[Fact]
public async Task CreateAccountAsync_NewAccount_ReturnsAccountReadDto()
{
var expectedAccount = CreaterandomAccount(); // has id
var createDto = _mapperStub.Map<AccountCreateDto>(expectedAccount); // doesn't have id
_repoStub
.Setup(repo => repo.CreateAccountAsync(expectedAccount))
.Returns(Task.CompletedTask);
var controller = new AccountController(_repoStub.Object,_mapperStub);
var actionResult = await controller.CreateAccountAsync(createDto);
var result = (actionResult.Result as CreatedAtRouteResult).Value as AccountReadDto;
result.Should().BeEquivalentTo(
expectedAccount,options => options.ComparingByMembers<AccountReadDto>().ExcludingMissingMembers() // excluding login info
);
}
解决方法
此代码不正确:
_repoStub
.Setup(repo => repo.CreateAccountAsync(expectedAccount))
设置 CreateAccountAsync
只是为了将 expectedAccount
实例作为参数传递的情况。 (映射后就不一样了)。使用 It.IsAny<T>()
配置方法以使用任何参数。然后使用 Callback<T>(Action<T>)
访问传递给模拟调用的参数:
_repoStub
.Setup(repo => repo.CreateAccountAsync(It.IsAny<Account>()))
.Callback<Account>(a => a.Id = expectedAccount.Id)
.Returns(Task.CompletedTask);
在该代码中,您将 CreateAccountAsync
方法配置为返回 Task.CompletedTask
并将传入参数 id 修改为 expectedAccount.Id
。
Returns(Task.CompletedTask)
可以省略。 (这是默认行为)
关于 Callback<T>
的其他信息:link