开发者

Unit test to check if an action method called the service layer

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 jso开发者_高级运维nResult = 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;
}


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.


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.


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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜