2010-12-08 44 views
2

Tenir compte des interfaces de service suivantes:En utilisant RhinoMocks, comment puis-je affirmer qu'une de plusieurs méthodes a été appelée?

public interface IServiceA 
{ 
    void DoSomething(string s); 
    void DoSomething(string s, bool b); 
} 

public interface IServiceB 
{ 
    void DoSomething(); 
} 

La mise en œuvre de IServiceB dépend de IServiceA comme ceci:

public class ServiceB : IServiceB 
{ 
    private IServiceA _serviceA; 

    public ServiceB(IServiceA serviceA) 
    { 
     _serviceA = serviceA; 
    } 

    public void DoSomething() 
    { 
     _serviceA.DoSomething("Hello", true); 
    } 
} 

Ie. la dépendance est injectée dans le constructeur.

Considérons maintenant un test unitaire pour la méthode DoSomething(). Je souhaite affirmer que l'une des méthodes DoSomething surchargées dans IServiceA est appelée, mais en suivant un principe général que les tests unitaires ne devraient pas trop savoir sur les rouages ​​internes de la méthode testée, je souhaite être indifférent à savoir lequel des tests unitaires deux surcharges sont appelées. Considérons le test unitaire suivant:

[TestFixture] 
public class ServiceBTests 
{ 
    [Test] 
    public void DoSomething_CallsServiceA() 
    { 
     var serviceAMock = MockRepository.GenerateMock<IServiceA>(); 
     var service = new ServiceB(serviceAMock); 

     service.DoSomething(); 

     // Problem: How to check if EITHER: 
     serviceAMock.AssertWasCalled(s => s.DoSomething(Arg<String>.Is.NotNull, Arg<bool>.Is.Anything)); 
     // OR: 
     serviceAMock.AssertWasCalled(s => s.DoSomething(Arg<String>.Is.NotNull)); 
    } 
} 

Comment puis-je affirmer que soit un ou l'autre des deux méthodes a été appelé?

+0

Hmm. Peut-être que ma pensée est faussée ici. Je suppose que le test unitaire devrait s'assurer que DoSomething() fait exactement ce qu'il devrait faire. Et tandis que le fonctionnement interne de la méthode ne concerne pas le test unitaire, savoir exactement ce que la méthode devrait faire implique, peut-être, de savoir exactement quelle surcharge doit être appelée. Des opinions à ce sujet? –

Répondre

4

Vous pouvez définir manuellement un drapeau booléen comme ceci:

[TestFixture] 
public class ServiceBTests 
{ 
    [Test] 
    public void DoSomething_CallsServiceA() 
    { 
     var serviceAMock = MockRepository.GenerateMock<IServiceA>(); 
     bool called = false; 
     serviceAMock.Stub(
      x => x.DoSomething(Arg<String>.Is.NotNull, Arg<bool>.Is.Anything)) 
      .WhenCalled(delegate { called = true; }); 
     serviceAMock.Stub(x => x.DoSomething(Arg<String>.Is.NotNull)) 
      .WhenCalled(delegate { called = true; }); 

     var service = new ServiceB(serviceAMock); 

     service.DoSomething(); 

     Assert.IsTrue(called); 
    } 
} 

Je ne pense pas que cela très utile cependant. Les tests unitaires concernent tout ce qui peut être observé depuis l'extérieur des limites du composant. Les appels de méthodes aux simulacres en font partie. En d'autres termes, il est OK si vous testez pour une surcharge spécifique appelée. Après tout, il doit y avoir une raison pour laquelle vous utilisez cette surcharge et pas l'autre.

Si vous voulez vraiment que le test d'unité reste ignoré de l'implémentation, vous ne pourrez pas du tout affirmer les appels de méthode sur les mocks. Ce serait une restriction sévère sur votre capacité à écrire des tests.

+1

Oui. Vous avez peut-être vu mon commentaire ci-dessus, il reflète une réalisation dans ce sens. J'ai donc écrit mes tests unitaires pour des appels spécifiques après tout. Mais merci pour le conseil quand même. Il pourrait être utile dans des cas spéciaux. –

+0

Je suis tombé sur une situation très similaire en utilisant NSubstitute. Ne pourriez-vous pas argumenter que peu importe quelle méthode a été appelée, tant que le comportement était le même? Les tests axés sur le comportement ne sont-ils pas meilleurs la plupart du temps? – julealgon