单元测试和SRP(测试方法范围/组织)
假设我有一个 MVC 操作,例如:
public ActionResult CustomerRecord(customerId)
{
if (_currentUser.CanViewCustomer(customerId))
return View();
else
{
// user has tried to access an unauthorised record,
// should not be here!
_logger.Log(new SecurityException());
return View("UnauthorizedAccess");
}
}
要测试未经授权的访问尝试的情况,应该有多少个测试方法?
即我是否编写一个测试:
CustomerRecord_WithUnauthorizedUser_LogsExceptionAndReturnsUnauthorizedView
或者我是否编写两个测试:
CustomerRecord_WithUnauthorizedUser_LogsException
CustomerRecord_WithUnauthorizedUser_ReturnsUnauthorizedView
我想问题是技术上控制器违反了SRP,但我不认为这本身就是一个问题(如果您不同意,请纠正我)。我只是不确定这如何映射到测试方法。该方法的每个职责进行一次测试,还是该方法的每个单一路径进行一次测试?
Say I have an MVC Action like:
public ActionResult CustomerRecord(customerId)
{
if (_currentUser.CanViewCustomer(customerId))
return View();
else
{
// user has tried to access an unauthorised record,
// should not be here!
_logger.Log(new SecurityException());
return View("UnauthorizedAccess");
}
}
To test the case of an unauthorized access attempt, how many test methods should there be?
i.e. do I write a single test:
CustomerRecord_WithUnauthorizedUser_LogsExceptionAndReturnsUnauthorizedView
or do I write two tests:
CustomerRecord_WithUnauthorizedUser_LogsException
CustomerRecord_WithUnauthorizedUser_ReturnsUnauthorizedView
I guess the problem is that technically the controller violates SRP, but I don't see that as being a problem in itself (please correct me if you disagree). I'm just not sure how that maps to test methods. One test per responsibility of the method, or one test per single route through the method?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您的控制器不一定会因为做两件事而违反 SRP - 它仍然只有一项责任(控制)。
在这个特定的示例中,我会警告不要断言进行了日志调用 - 如果您取出日志语句,它不会影响应用程序的功能。过度指定的单元测试会使它们变得脆弱并且难以维护,这也是我如此喜欢 BDD 的部分原因。
如果您必须审核每一次失败的尝试,那么我想这值得进行单元测试,所以如果这就是您正在做的事情,请继续阅读:
一般来说,您应该只有一个断言(也许您会有每个单元测试调用一个或两个 Assert 方法来进行一个语义断言)——基本上是因为能够查看失败测试的名称并准确地知道出了什么问题而无需查看代码,这是很好的。所以我建议进行两次测试...
Your controller isn't necessarily violating SRP by doing two things - it's still only got one responsibility (controlling).
In this specific example, I would caution against asserting that a log call is made - it's not going to affect the functionality of your application if you take out the log statement. Overspecifying unit tests makes them brittle and a pain to maintain, which is part of the reason I like BDD so much.
If you had to audit every failed attempt then I guess that's worth unit testing, so if that's what you're doing then read on:
In general, you should only have one assertion (maybe you'd have to call an Assert method or two to make one semantic assertion) per unit test - basically because it's nice to be able to look at the name of the failed test and to know exactly what's gone wrong without having to look at the code. So I'd advocate having two tests...
我更喜欢每个测试一个断言(或者你所说的责任),因为如果出现问题,可以立即清楚代码路径的哪一部分失败了。这假设您以阅读测试结果时可以理解的方式命名您的测试(您的示例)。
I prefer the one assert per test (or responsibility as you put it) because it's instantly clear what part of the code path has failed if there is a problem. This assumes you name your tests (your examples do) in a way that's understandable when reading your test results.