2009-03-11 8 views
3

Mit dem neuen Rhino Mocks 3.5 Anordnen/Act/Assert (AAA) Teststil, habe ich Probleme beim Schreiben eines Tests.Verwenden von Rhino Mocks Wie kann ich eine Eigenschaft eines Parameters für eine Mocked-Methode festlegen

Ich habe eine Methode, die eine Methode für eine Repository-Klasse aufruft. ActivateFoo, wo mein Foo-Objekt eine IsActive-Eigenschaft hat. Das Ergebnis des ActivateFoo-Objekts sollte die Eigenschaft ändern. Hier

ist Beispielcode: "ActivateFoo (foo))"

[TestMethod] 
public void Should_update_foo_to_active_inside_of_repository() 
{ 
    // arrange 
    var repo = MockRepository.GenerateMock<IRepository>(); 
    var foo = new Foo() { ID = 1, IsActive = false }; 
    var target = new Presenter(repo); 
    repo.Expect(x => x.ActivateFoo(foo)).Return(true); 

    // act 
    target.Activate(foo); 

    // assert 
    Assert.IsTrue(foo.IsActive); 
    repo.VerifyAllExpectations(); 
} 

Ich vermute, dass der Schlüssel Stück Code dazwischen wäre und "Zurück (wahr);".

Ein Punkt, um zu klären, wie die Methode Verkettung funktioniert hinter den Kulissen, Wenn es Code in der Zeile, die ich erwarte, ist es wichtig, ob es nach Return() oder vorher ist? (es sei denn, die Lösung nutzt die MethodOptions-Überladung von Expect oder etwas anderes).

Vielen Dank im Voraus für jede Hilfe.

+0

Bitte klären Sie die Struktur und die Beziehung Ihrer Klassen. Die Beziehung zwischen Foo & Presenter ist aus deinem Beispiel nicht ganz klar. Erweitere auch ActivateFoo (foo) & Activate (foo) im Presenter. – abhilash

Antwort

0

Sie möchten vielleicht etwas ausprobieren, indem Sie den Do-Handler verwenden. Ich glaube wirklich, dass ActivateFoo ein ungültiger Rückgabetyp sein sollte. Aber hier ist der Code für ActivateFoo mit Bool-Return-Typ.

[TestMethod] 
    public void Should_update_foo_to_active_inside_of_repository() 
    { 
     // arrange 
     var repo = MockRepository.GenerateMock<IRepository>(); 
     var foo = new Foo() { ID = 1, IsActive = false }; 
     var target = new Presenter(repo); 
     repo.Expect(x => x.ActivateFoo(foo)). 
      Do(new ActivateFooDelegate(ActivateFooDelegateInstance)); 
     // act 
     target.Activate(foo); 

     // assert 
     Assert.IsTrue(foo.IsActive); 
     repo.VerifyAllExpectations(); 
    } 

    private delegate bool ActivateFooDelegate(Foo f); 

    public bool ActivateFooDelegateInstance(Foo f) 
    { 
     f.IsActive = true; 
     return f.IsActive; 
    } 
0

Ich habe diese Version von RhinoMocks noch nicht wirklich benutzt, aber in den alten Versionen müssten Sie einen .Do (entsprechenden Delegaten) verwenden, um das Flag zu setzen und den Wert zurückzugeben (anstelle von .Return).

Bitte lassen Sie mich wissen, wenn es funktioniert, wenn nicht kann ich damit umgehen.

0

Aus den Augen sollte ActivateFoo eine void-Methode sein. Und da du dich darüber lustig machst, solltest du nicht verifizieren, dass es irgendetwas an deinem Objekt verändert.

Sie würden überprüfen, dass die IsActive-Eigenschaft beim Testen der Repository-Methode ActivateFoo geändert wurde, nicht beim Testen der Activate-Methode für den Referenten.

1

Dank AB Kolan ist dies der resultierende Code, den ich verwendet und funktioniert.

[TestMethod] 
public void Should_update_foo_to_active_inside_of_repository() 
{ 
    // arrange 
    var repo = MockRepository.GenerateMock<IRepository>(); 
    var foo = new Foo() { ID = 1, IsActive = false }; 
    var target = new Presenter(repo); 
    repo.Expect(x => x.ActivateFoo(foo)). 
     Do(new Func<Foo, bool>(
      delegate(Foo f) { f.IsActive = true; return true; } 
     )); 

    // act 
    target.Activate(foo); 

    // assert 
    Assert.IsTrue(foo.IsActive); 
    repo.VerifyAllExpectations(); 
} 

Ich neige dazu, nicht für die einmaligen Gebrauch eines Tests zu erheben zusätzliche Methoden der Funktionen haben zu mögen, einen Inline-Delegaten, wenn möglich lieber.

Um das Problem der ist das etwas, was ich tun sollte oder nicht so weit wie das Design. Wie die Namen dort sind, ist dies nicht der genaue Code und innerhalb der Ziel.Activate() -Methode. Der Code in Activate() führt einige Überprüfungen durch und führt bei Bedarf das Repository ActivateFoo() aus, überprüft dann das Ergebnis dieser Operation und führt andere Aktionen aus.

Also könnte es möglich sein, dass ich zu einem späteren Zeitpunkt muss ich dies umgestalten und die Schritte trennen, aber für den Moment habe ich es zur Arbeit.

Danke

Verwandte Themen