规范与规范rhino 模拟预期异常测试
我对单元测试相当陌生,无法解决如何正确测试(或者我什至应该)这种情况的问题。
我有一个控制器方法(伪代码):
public ActionResult Register(formModel model)
{
if (ModelState.isValid) {
try {
_userService.CreateUser(a bunch of parameters here);
return RedirectToAction(some other action);
}
catch (Exception e)
{
ModelState.AddModelError("",e.Message);
}
}
return View();
}
我有一堆针对“_userService”的单独测试。 “CreateUser”方法只是创建一个新用户并且不返回任何内容,或者如果出现错误(例如用户存在),则抛出异常,我在 try catch 中冒泡到控制器周围并将异常添加到 ModelState。
据我了解,我应该模拟该服务并断言它被正确调用(我使用assertwas称为语法),因为它什么也不返回,我只想知道我的控制器调用了它。
我不确定如何测试当用户服务抛出错误时它不应该重定向并且应该将该异常添加到模型状态中。使用 rhino 模拟,您可以存根模拟,但单元测试的书籍艺术建议不要这样做。
现在,在我的测试中,我手动添加模型错误(不关心它是否来自用户服务)并测试控制器是否在出现错误时返回相同的视图。这是解决这个问题的正确方法吗?或者我应该创建一个单独的测试,在其中存根 _userService 以引发错误并检查它是否添加到模型状态?或者我什至不应该测试这个案例?我觉得我可能只是过度分析了整个事情,并且使用 modelstate 进行测试就足以满足这一点......
I'm fairly new to unit testing and can't get around how to test (or if I even should) this case properly.
I have a controller method (pseudo code):
public ActionResult Register(formModel model)
{
if (ModelState.isValid) {
try {
_userService.CreateUser(a bunch of parameters here);
return RedirectToAction(some other action);
}
catch (Exception e)
{
ModelState.AddModelError("",e.Message);
}
}
return View();
}
I have a bunch of separate tests against "_userService". The "CreateUser" method just creates a new user and returns nothing OR throws an exception if there was an error (ex. the user exists) that I bubble up to the controller surround in a try catch and add the exception to the ModelState.
From what I understand I should mock the service and assert that it was called correctly (i use the assertwascalled syntax) since it returns nothing and I just want to know that my controller calls it.
What I'm not sure is how to test that when the userservice throws an error it should not redirect and should add that exception to the modelstate. With rhino mocks you can stub a mock but the book art of unit testing advises against that.
Right now in my test I manually add a model error (not caring if it's from user service) and test that the controller returns the same view if there are errors. Is this the correct way of going about this? Or should I maybe create a separate test where I stub the _userService to throw an error and check it gets added to modelstate? Or should I not even test that case? I feel like I may be just over analyzing the whole thing and testing using the modelstate would be enough to satisfy this...
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您的模拟代表一个协作类。我不会太在意模拟和存根之间的区别;它仍然是一个协作类。
您可以将单元测试视为描述如何使用您的类,以及该类如何与其协作者交互。您有两个示例:
并且:
第二个
Given
告诉您您正在存根而不是嘲笑。您正在设置用户服务,就好像它已损坏一样。类运行的上下文不同,因此您需要存根,并且确实应该抛出异常。如果您将这些行作为注释放入测试中,那就有意义了。如果有道理,请忽略这本书。
顺便说一句,这是单元级 BDD。您可以在单元级别使用“Given、When、Then”,就像在场景级别一样,它可能会帮助您思考测试的逻辑。只是不要为此使用 BDD 场景工具。
Your mock represents a collaborating class. I wouldn't get too hung up on the difference between mocks and stubs; it's still a collaborating class.
You can think of your unit tests as describing how to use your class, and how the class then interacts with its collaborators. You have two examples:
And:
It's that second
Given
that tells you you're stubbing rather than mocking. You're setting the user service up as though it's broken. The context in which the class acts is different, so you need to stub, and you should indeed throw an exception.If you put these lines as comments inside your test, it'll make sense. If it makes sense, ignore the book.
BTW, this is unit-level BDD. You can use "Given, When, Then" at a unit level just as at a scenario level, and it might help you think about the logic of your tests. Just don't use BDD scenario tools for this.