单元测试检查某个操作方法是否调用了服务层
我有一个名为 NewsController 的控制器,该控制器的构造函数接收 INewsService 作为参数。
我在这个控制器中有一个名为 GetAllNews() 的方法,它返回一个 JSON 结果,我用它来填充 YUI 数据表。我想编写一个单元测试来检查是否调用新闻服务的 FindAll 方法来返回所有新闻项。我该怎么做?我目前拥有的是:
public JsonResult GetAllNews()
{
var items = newsService.FindAll();
var jsonResult = Json(items);
return jsonResult;
}
我的控制器单元测试如下所示:
public NewsControllerTest()
{
newsServiceStub = MockRepository.GenerateStub<INewsService>();
newsController = new NewsController(newsServiceStub);
}
[Test]
public void GetAllNews_should_use_news_service()
{
// Arrange
List<News> newsList = new List<News>();
newsServiceStub.Stub(s => s.FindAll()).Return(newsList);
// Act
var actual = newsController.GetAllNews();
// Assert
newsServiceStub.VerifyAllExpectations();
}
测试通过上述代码。但如果我将 GetAllNews() 更改为如下所示,那么它也会通过。不应该失败吗?我想测试的是 GetAllNews() 是否使用新闻服务:
public JsonResult GetAllNews()
{
return null;
}
I have a controller called NewsController, the constructor of this controller receives an INewsService as parameter.
I have a method in this controller called GetAllNews() that returns a JSON result that I use to populate a YUI datatable. I want to write a unit test that checks if the news service's FindAll method was called to return all the news items. How would I do this? What I currently have is:
public JsonResult GetAllNews()
{
var items = newsService.FindAll();
var jsonResult = Json(items);
return jsonResult;
}
My unit test for the controller looks like:
public NewsControllerTest()
{
newsServiceStub = MockRepository.GenerateStub<INewsService>();
newsController = new NewsController(newsServiceStub);
}
[Test]
public void GetAllNews_should_use_news_service()
{
// Arrange
List<News> newsList = new List<News>();
newsServiceStub.Stub(s => s.FindAll()).Return(newsList);
// Act
var actual = newsController.GetAllNews();
// Assert
newsServiceStub.VerifyAllExpectations();
}
The test passes with the above code. But if I were to change GetAllNews() to look like below then it also passes. Shouldn't it fail? What I am trying to test is if GetAllNews() uses the news service:
public JsonResult GetAllNews()
{
return null;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
如果您可以逃脱惩罚,请不要对调用的特定方法进行单元测试。单元测试的重点是测试行为,而不是实现。测试调用
FindAll
就是测试实现。这会导致脆弱的测试,如果您更改实现但行为没有改变,测试就会中断。客户并不关心你如何获得所有新闻,他们只是希望你获得所有新闻。,
应该如此
我将把编码的细节留给您。
If you can get away with it, don't unit test that a particular method was called. The point of unit testing is to test behavior, not implementation. Testing that
FindAll
is called is testing an implementation. This leads to brittle tests that break if you change the implementation but the behavior doesn't change. Clients don't care how you get them all the news, they just want you get them all of the news.So
should be
and I'll leave the details of coding that up to you.
正如其他人指出的那样,从长远来看,对特定方法调用的测试可能很脆弱。
然而,从 Rhino.Mocks 的角度来看,如果您想检查期望,您应该使用 Mock 而不是 Stub。将
GenerateStub
更改为GenerateMock
,并将.Stub()
调用更改为.Expect()
调用。这应该可以解决你的测试问题。As others have pointed out, testing for particular method calls can be brittle in the long run.
However, from a Rhino.Mocks standpoint, if you want to check expectations, you should be using a Mock instead of a Stub. Change you
GenerateStub
to aGenerateMock
and your.Stub()
call to an.Expect()
call. That should fix your test.您可能会发现 Martin Fowler 撰写的这篇关于模拟和存根之间差异的文章很有趣。
http://www.martinfowler.com/articles/mocksArentStubs.html
Fowler 指出存根用于状态验证,而模拟用于行为验证。
You might find this article by Martin Fowler interesting on the differences between mocks and stubs.
http://www.martinfowler.com/articles/mocksArentStubs.html
Fowler points out stubs are used for state verification while mocks are used for behavior verification.