62 votes

Comment effacer les attentes antérieures sur un objet ?

J'aimerais mettre en place une valeur de retour

_stubRepository.Stub(Contains(null)).IgnoreArguments().Return(true);

mais ensuite, dans un test spécifique, remplacer cette attente pour renvoyer false.

Quelque chose comme :

_stubRepository.ClearExpectations();  //<- this does not exist, I'm just making something up
_stubRepository.Stub(Contains(null)).IgnoreArguments().Return(false);

Notez que je ne veux pas que l'attente renvoie false lors du deuxième appel, je veux passer outre la première attente.

Cela simplifierait grandement mon scénario de test.

78voto

Stefan Steinegger Points 37073

Il y a trois façons de procéder :

Vous pouvez réinitialiser les attentes en utilisant BackToRecord

Je dois admettre que je ne l'ai jamais vraiment utilisé parce qu'il est peu pratique.

// clear expectations, an enum defines which
_stubRepository.BackToRecord(BackToRecordOptions.All);
// go to replay again.
_stubRepository.Replay();

Edita: Maintenant que je l'utilise parfois, c'est en fait la méthode la plus propre. Il devrait y avoir une méthode d'extension (comme Stub) qui le fait - je pense qu'elle a été oubliée. Je vous suggère d'écrire la vôtre.

Vous pouvez utiliser Repeat.Any()

Il "rompt" l'ordre de la définition de l'extrait et "écrase" les définitions précédentes. Mais c'est en quelque sorte implicite. Je l'utilise parfois parce qu'elle est facile à écrire.

_stubRepository.Stub(x => x.Contains(null))
  .IgnoreArguments()
  .Return(false)
  .Repeat.Any();

Vous pouvez créer un nouveau simulacre

Trivial, mais explicite et facile à comprendre. Le problème ne se pose que si l'on souhaite conserver un grand nombre de définitions et ne modifier qu'un seul appel.

_stubRepository = MockRepository.GenerateMock<IRepository>();
_stubRepository.Stub(x => x.Contains(null))
  .IgnoreArguments()
  .Return(false);

22voto

MoMo Points 5587

Pour ces situations, j'ai créé une méthode d'extension RinoMocks simple pour mieux montrer l'intention du stub et favoriser la lisibilité.

public static void OverridePrevious<T>(this IMethodOptions<T> options)
{
    options.Repeat.Any();
}

Ainsi, au lieu d'un appel cryptique comme le suivant qui peut nécessiter un commentaire :

[SetUp]
public void Setup()
{
    carStub.Stub(x => x.Model).Return("Model1");
    carStub.Stub(x => x.Model).Return("Model2");
}

[Test]
public void SomeTest()
{
    //Arrange
    //overrides previous stubs that were setup for the Model property
    carStub.Stub(x => x.Model).Return(null).Repeat.Any();

    //Act
    //Assert
}

Vous pouvez obtenir un test plus lisible qui montre mieux l'intention des appels .Repeat.Any() :

carStub.Stub(x => x.Model).Return(null).OverridePrevious();

8voto

Micah Hahn Points 52

Pour le bien de la communauté, j'ajouterai ceci à la liste d'options de Stefan ci-dessus :

Si la valeur de retour doit être modifiée fréquemment, je trouve qu'il est propre et efficace d'utiliser une fermeture comme suit.

bool returnValue = true;
_stubRepository.Stub(x => x.Contains(null)).IgnoreArguments().Do(new Func<bool>(() => {
    return returnValue;
}));

returnValue = false;
// Calls to Contains now return false;

returnValue = true;
// Calls to Contains now return true;

L'expression lambda sera exécutée à chaque fois que Contains est appelée et parce que nous avons créé une fermeture faisant référence à returnValue il recherchera toujours le actuel valeur de returnValue .

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X