2010-12-08 4 views
2

Betrachten Sie die folgende Service-Schnittstellen:Wie kann ich mit RhinoMocks feststellen, dass eine von mehreren Methoden aufgerufen wurde?

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

public interface IServiceB 
{ 
    void DoSomething(); 
} 

Die Implementierung von IServiceB hängt von IServiceA wie folgt aus:

public class ServiceB : IServiceB 
{ 
    private IServiceA _serviceA; 

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

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

Ie. Die Abhängigkeit wird in den Konstruktor eingefügt.

Betrachten Sie nun einen Komponententest für die Methode DoSomething(). Ich möchte behaupten, dass eine der überladenen DoSomething-Methoden in IServiceA aufgerufen wird, aber nach einem allgemeinen Prinzip, dass Komponententests nicht zu viel über die internen Abläufe der zu testenden Methode wissen sollten, möchte ich agnostisch sein, welche der zwei Überladungen wird aufgerufen. Betrachten Sie die folgende Einheit Test:

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

Wie kann ich behaupten, dass entweder ein oder die andere der beiden Methoden aufgerufen wurde?

+0

Hmm. Vielleicht ist mein Denken hier verzerrt. Ich denke, der Unit-Test sollte sicherstellen, dass DoSomething() genau das tut, was es sollte. Und während die internen Abläufe der Methode nicht den Komponententest betreffen, führt es vielleicht dazu, genau zu wissen, was die Methode tun sollte, genau zu wissen, welche Überladung aufgerufen werden sollte. Irgendwelche Meinungen dazu? –

Antwort

4

Sie können manuell einen boolean-Flag wie so gesetzt:

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

Ich glaube nicht, diese sehr nützlich though. Unit-Tests befassen sich mit allem, was von außerhalb der Komponentengrenzen beobachtbar ist. Methodenaufrufe an Mocks gehören dazu. Mit anderen Worten, es ist in Ordnung, wenn Sie testen, ob eine bestimmte Überladung aufgerufen wird. Schließlich muss es einen Grund geben, warum Sie diese Überladung benutzen und nicht die andere.

Wenn Sie wirklich möchten, dass der Komponententest die Implementierung ignoriert, dürfen Sie Methodenaufrufe überhaupt nicht auf Mocks anwenden. Das wäre eine starke Einschränkung für Ihre Fähigkeit, Tests zu schreiben.

+1

Ja. Vielleicht hast du meinen Kommentar oben gesehen, er spiegelt eine Erkenntnis in dieser Richtung wider. Also habe ich immerhin meine Unit-Tests für bestimmte Anrufe geschrieben. Aber danke für den Tipp trotzdem. Es könnte in besonderen Fällen nützlich sein. –

+0

Ich stolperte über eine sehr ähnliche Situation mit NSubstitute. Könnten Sie nicht argumentieren, dass es egal wäre, welche Methode aufgerufen wurde, solange das Verhalten das gleiche war? Ist das Verhalten nicht meist besser getestet? – julealgon

Verwandte Themen