MSTest框架如何处理依赖于其他单元测试的单元测试?我正在测试一个REST API,并且花了相当多的时间试图理解它的全貌。在这次旅行中出现了以下问题:
- 我们应该编写调用其他测试方法的测试方法吗?它是否在某种程度上违背了单元测试的想法?或者单元测试应该彼此完全隔离?
- 如果隔离,当某些api端点需要的输入只能通过调用另一个api端点(已经存在测试)来获取时,我们该怎么办?例如,端点
GetMembers
端点需要认证令牌,该令牌只能通过调用Login
端点获得。每个端点都有一个单独的测试。从TestGetMembers
调用TestLogin
方法是公平的,还是我应该在TestGetMembers
内重复TestLogin
的整个代码(或编写一个函数来共享代码)? - 我应该在哪里保存登录令牌,因为所有后续测试都需要它。看起来MSTest为每个测试方法创建了测试类的新实例,因此我的全局变量丢失了。是否可以声明
static
变量来保存这些值? async
测试怎么样?我的研究表明,async
测试可以返回Task
,但不能返回Task<T>
。Visual Studio Test Explorer没有列出任何返回Task<T>
并尝试手动运行它们的测试方法(例如,在方法内部右键单击并选择Run Test
),而没有实际运行测试方法。有这样的限制吗?如果是,我怎么能从异步测试方法返回值,将被另一个测试方法消耗?
我主要回答你的第一个问题。如果你能够模拟服务器的行为,你可以测试端点方法,但在我看来,这是超过工程。单元测试是为测试单元逻辑而设计的。在良好的设计中,您将逻辑注入控制器(例如,作为服务、facade或其他体系结构对象),并且您需要测试被注入的方法。在下面的代码中,我没有测试GetById控制器方法,而是测试_facade.MyMethod()。如果在控制器方法中有更复杂的逻辑,则应该将其移到另一层。如果您要测试facade逻辑,就像我在示例中写的那样,您可以省略身份验证,因为您不需要令牌,尽管它也取决于您的授权机制。
public class MyExampleObjectController : ControllerBase
{
private readonly IExampleObjectFacade _facade;
public MyExampleObjectController(IExampleObjectFacade facade)
{
_facade = facade;
}
[HttpGet]
[Authorize]
[ProducesResponseType(200)]
[ProducesResponseType(404)]
public async Task<IActionResult> GetById(Guid id,
CancellationToken cancellationToken = default)
{
var item = await _facade.MyMethod(id, cancellationToken);
if (item == null)
{
return NotFound();
}
return Ok(item);
}
}