2010-12-13 42 views
0

J'ai un contrôleur appelé NewsController, le constructeur de ce contrôleur reçoit un INewsService comme paramètre.Test d'unité pour vérifier si une méthode d'action appelée la couche de service

J'ai une méthode dans ce contrôleur appelé GetAllNews() qui retourne un résultat JSON que j'utilise pour remplir une donnée YUI. Je veux écrire un test unitaire qui vérifie si la méthode FindAll du service de presse a été appelée pour renvoyer tous les éléments de nouvelles. Comment ferais-je cela? Ce que j'ai actuellement est:

public JsonResult GetAllNews() 
{ 
    var items = newsService.FindAll(); 
    var jsonResult = Json(items); 

    return jsonResult; 
} 

Mon test unitaire pour le contrôleur ressemble à:

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(); 
} 

Le test passe avec le code ci-dessus. Mais si je devais changer GetAllNews() pour ressembler à ci-dessous, il passe également. Ne devrait-il pas échouer? Ce que je suis en train de tester est si GetAllNews() utilise le service de nouvelles:

public JsonResult GetAllNews() 
{ 
    return null; 
} 
+0

En note, pourquoi considérez-vous cela comme un test utile? – bzlm

+0

@bzim: Je suis un débutant, j'apprends encore. Ce n'est pas toujours clair pour moi ce qu'il faut tester et quoi ne pas faire. –

Répondre

3

Si vous pouvez vous en sortir avec elle, ne pas test unitaire qu'une méthode particulière a été appelée. Le but des tests unitaires est de tester le comportement, pas la mise en œuvre. Test que FindAll est appelé teste une implémentation. Cela conduit à des tests fragiles qui cassent si vous modifiez l'implémentation mais que le comportement ne change pas. Les clients ne se soucient pas de savoir comment vous les avez toutes les nouvelles, ils veulent juste que vous leur donniez toutes les nouvelles.

Alors

public void GetAllNews_should_use_news_service() 

devrait être

public void GetAllNews_should_get_all_the_news 

et je vais laisser les détails de codage que jusqu'à vous.

+0

Par comportement, vous voulez dire? Quel serait le comportement dans ma méthode GetAllNews()? Si vous nommez le test GetAllNews_should_get_all_the_news, qu'incluriez-vous dans le code de test? Pouvez-vous s'il vous plaît fournir un échantillon de code s'il vous plaît dans votre réponse ci-dessus? –

1

Comme d'autres l'ont souligné, les tests pour des appels de méthode particuliers peuvent être fragiles à long terme. Cependant, du point de vue de Rhino.Mocks, si vous voulez vérifier les attentes, vous devriez utiliser un Mock au lieu d'un Stub. Changez GenerateStub en GenerateMock et votre appel .Stub() en appel .Expect(). Cela devrait réparer votre test.

+0

Quelle est la différence entre faux et talon? Quand dois-je utiliser les deux? –

+0

Les talons sont utilisés pour fournir des réponses standardisées. Les mocks sont utilisés pour vérifier les attentes. Vous pouvez utiliser des simulacres pour fournir des réponses prédéfinies, mais les talons ne suivent pas les appels de méthode et ne peuvent donc pas être utilisés pour valider les attentes. – PatrickSteele

1

Cet article de Martin Fowler pourrait vous intéresser sur les différences entre les mock et les stubs.

http://www.martinfowler.com/articles/mocksArentStubs.html

Fowler rappelle les talons sont utilisés pour la vérification de l'état tout simulacres sont utilisés pour la vérification du comportement .