我有一个使用Entity Framework设置的ASP.NET核心(.NET Framework)项目,用于处理我的数据库。我在我的解决方案中创建了一个单独的测试项目。
我将如何为“注册”,“注册”等终端编写单元测试?
以下是我的RegisterUser端点的片段。
public async Task<IActionResult> RegisterUser(string email, string name, string password)
{
var user = new User { UserName = email, Email = email, Name = name };
IdentityResult resultCreate = null;
if (email.EndsWith("@stud.ntnu.no") || email.EndsWith("@ntnu.no"))
{
// Student or teacher?
var role = (email.EndsWith("@stud.ntnu.no") ? "Student" : "Teacher");
resultCreate = await _userManager.CreateAsync(user, password);
if (resultCreate.Succeeded)
{
// Add role
var resultRole = await _userManager.AddToRoleAsync(user, role);
if (resultRole.Succeeded)
{
// Sign in
await _signInManager.SignInAsync(user, true);
return Ok();
}
}
}
// Error
return StatusCode(400, resultCreate?.Errors);
}
答案 0 :(得分:2)
根据原帖后面的评论判断,实际问题似乎是“如何避免持续存在单元测试数据?”
有很多方法可以解决这个问题:
单元测试应该只测试一件事,其他一切都应该被模拟。因此,模仿您的_userManager
和_signInManager
。由于它们被嘲笑,它们不会持久存在,因此避免测试数据持久性是免费的。根据我的经验,这是一种相当迟钝的测试方法,我强烈建议反对它。
其他方法首先要意识到您实际上并没有编写单元测试,而是编写集成测试,因为您正在测试与数据库层集成的应用程序逻辑。
使用内存数据库,让每个测试创建一个在测试结束时丢弃的新数据库。不幸的是,这意味着重新启动整个数据库层,如果你像ORM一样使用重量级的东西,这意味着每次测试都会增加巨大的性能开销。
让每个测试方法启动一个事务,一旦完成,就回滚它。这是做事的首选方式。在某些情况下,您甚至可以使用@Transactional
注释您的测试方法,如果所有其他所需的魔法是正确的,那么可能会为您处理事务。再说一遍,注释你永远不会知道某件事是否真的会发生,在这种情况下,如果事务性没有发生那么你就毁了你的数据库,所以我的偏好是从@Transactional
保持清醒并编码我的交易开始和我自己的事务回滚。