单元测试检查某个操作方法是否调用了服务层

发布于 2024-10-08 00:41:20 字数 1027 浏览 2 评论 0原文

我有一个名为 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

郁金香雨 2024-10-15 00:41:20

如果您可以逃脱惩罚,请不要对调用的特定方法进行单元测试。单元测试的重点是测试行为,而不是实现。测试调用 FindAll 就是测试实现。这会导致脆弱的测试,如果您更改实现但行为没有改变,测试就会中断。客户并不关心你如何获得所有新闻,他们只是希望你获得所有新闻。

public void GetAllNews_should_use_news_service()

应该如此

public void GetAllNews_should_get_all_the_news

我将把编码的细节留给您。

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

public void GetAllNews_should_use_news_service()

should be

public void GetAllNews_should_get_all_the_news

and I'll leave the details of coding that up to you.

平安喜乐 2024-10-15 00:41:20

正如其他人指出的那样,从长远来看,对特定方法调用的测试可能很脆弱。

然而,从 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 a GenerateMock and your .Stub() call to an .Expect() call. That should fix your test.

小嗷兮 2024-10-15 00:41:20

您可能会发现 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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文