2009-03-11 10 views
3

Utilisation du nouveau style de test Réorganiser/agir/affirmer (AAA) de Rhino Mocks 3.5, j'ai des difficultés à écrire un test.Utilisation de Rhino Mocks Comment puis-je définir une propriété d'un paramètre pour une méthode Mocked?

J'ai une méthode qui appelle une méthode sur une classe de référentiel. ActivateFoo, où mon objet Foo a une propriété IsActive. Le résultat de l'objet ActivateFoo doit changer la propriété.

Voici un exemple de code:

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

Je devine que la pièce clé du code serait inbetween "ActivateFoo (foo))." et "Retour (vrai)".

Un point pour clarifier le fonctionnement de la méthode de chaînage en coulisses. S'il y a du code écrit sur la ligne que j'attends, est-ce important si c'est après Return() ou avant? (à moins bien sûr que la solution utilise la surcharge MethodOptions d'Expect, ou autre chose).

Merci d'avance pour toute aide.

+0

Pls clarifier la structure et la relation de vos classes. La relation entre Foo & Presenter n'est pas très claire à partir de votre exemple. Développez également ActivateFoo (foo) et Activate (foo) dans le présentateur. – abhilash

Répondre

0

Vous pouvez essayer quelque chose comme ça en utilisant le gestionnaire Do. Honnêtement, je pense que ActivateFoo devrait être un type de retour vide. Mais voici le code pour ActivateFoo avec le type de retour booléen.

[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

Je n'utilisais pas encore cette version de RhinoMocks, mais dans les anciennes versions, vous deviez utiliser un .Do (délégué approprié) pour définir l'indicateur et renvoyer la valeur (au lieu de .Return).

S'il vous plaît laissez-moi savoir si cela fonctionne, sinon je peux jouer avec.

0

D'après son apparence, ActivateFoo devrait être une méthode vide. Et puisque vous vous moquez de vous, vous ne devriez pas vérifier que cela change quelque chose sur votre objet.

Vous vérifieriez que la propriété IsActive est modifiée lorsque vous étiez en train de tester votre méthode de référentiel ActivateFoo, pas lorsque vous testez la méthode Activate sur le présentateur.

1

Grâce à AB Kolan, c'est le code que j'ai utilisé et qui fonctionne.

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

J'ai tendance à ne pas avoir des méthodes supplémentaires de fonctions à usage unique d'un test, préférant un délégué en ligne si possible.

Pour résoudre le problème de est-ce quelque chose que je devrais faire ou pas en ce qui concerne la conception. Comme les noms sont là, ce n'est pas le code exact et l'intérieur de la méthode target.Activate(). Le code dans Activate() effectue une vérification et si nécessaire, fera le référentiel ActivateFoo(), puis vérifie le résultat de cette opération et fait d'autres choses.

Ainsi, il pourrait être possible que plus tard, je vais devoir refactoriser cela et séparer les étapes, mais pour l'instant, je l'ai pour fonctionner.

Merci

Questions connexes