如何避免保留单元测试数据?



我有一个使用实体框架设置的 ASP.NET 核心(.NET Framework)项目,用于处理我的数据库。我在解决方案中为测试创建了一个单独的项目。

我将如何为"注册"、"登录"等终结点编写单元测试?

这是我的注册用户端点的一个片段。

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);
}

从原始帖子下面的评论来看,实际问题似乎是"如何避免持久化单元测试数据?

您可以通过多种方式进行操作:

硬核的、真实的、教条式的单元测试方式:

单元测试应该只测试一件事,其他一切都应该被嘲笑。 所以,嘲笑你的_userManager和你的_signInManager. 由于它们被模拟,因此它们不会持久化任何内容,因此避免测试数据持久性是免费的。 根据我的经验,这是一种相当迟钝的测试方式,几乎可以测试任何东西,我强烈建议不要这样做。

其余的方法首先意识到您实际上并不是在编写单元测试,而是在编写集成测试,因为您正在测试与数据库层集成的应用程序逻辑。

内存数据库方式:

使用内存数据库,并让每个测试创建一个在测试结束时丢弃的新数据库。 不幸的是,这意味着重新启动整个数据库层,如果您使用的是像ORM这样的重量级产品,则意味着每次测试都会增加巨大的性能开销。

交易方式:

让每个测试方法启动一个事务,完成后,将其回滚。 这是首选的做事方式。 在某些情况下,您甚至可以用@Transactional注释您的测试方法,如果所有其他必需的魔法都是正确的,那么交易可能会为您处理。 再说一次,使用注释,你永远不知道某些事情是否真的会发生,在这种情况下,如果事务性没有发生,那么你就会破坏你的数据库,所以我的偏好是远离@Transactional并自己编写我的事务开始和事务回滚。

最新更新