2017-06-19 3 views
3

Disclaimer - ce n'est pas la même question que How to use FakeItEasy to assert a method was not calledAssertion qu'un appel n'a pas été faite avec des paramètres génériques utilisant FakeItEasy

Explication

J'ai un morceau de code qui enregistre des choses avec un conteneur du CIO , et je peux utiliser FakeItEasy dans mes tests pour m'assurer que les inscriptions sont faites. J'essaye de trouver comment s'assurer que les appels inattendus ne sont pas faits.

repo rapide (problème bouilli jusqu'à deux classes de test - ce n'est pas une véritable mise en œuvre)

public class Foo 
{ 
    private readonly ICustomContainer m_CustomContainer; 

    public Foo(ICustomContainer customContainer) 
    { 
     m_CustomContainer = customContainer; 
    } 

    public void Bar() 
    { 
     m_CustomContainer.Register<IMyInterface, IMyImplementation>(); 
    } 
} 

public interface ICustomContainer 
{ 
    void Register<TInterface, TImplementation>() where TImplementation : TInterface; 
} 

public class UnitTest1 
{ 
    [Fact] 
    public void Test1() 
    { 
     //Arrange 
     ICustomContainer fake = A.Fake<ICustomContainer>(); 
     Foo objectUnderTest = new Foo(fake); 

     //Act 
     objectUnderTest.Bar(); 

     //Assert 
     A.CallTo(() => fake.Register<IMyInterface, IMyImplementation>()).MustHaveHappened(); 
     //A.CallTo(() => fake.Register<???>()).MustNotHaveHappened(); //Any generic parameter apart from <IMyInterface, IMyImplementation> must not have happened 
    } 
} 

Le test ci-dessus passera - ce qui est correct. Si à l'avenir je devais ajouter un autre enregistrement dans le Bar(), il passerait toujours - ce qui n'est pas si bon que mon test ne fait que tester des scénarios connus.

Ce que je suis en train de réaliser Alors

, compte tenu de l'interface définie ci-dessus pour ICustomContainer qui est mon conteneur du CIO, je voudrais assurer qu'il est appelé uniquement comme prévu.

Ce que j'ai déjà enquêté

Après avoir utilisé d'autres cadres moqueurs dans le passé, comme Typemock Isolateur, je pourrais définir l'objet de faux à lancer des exceptions à moins que des appels spécifiques (attendus) sont faits. Je ne sais pas si je peux le faire avec FakeItEasy. De plus, TypeMock Isolator ne supporte pas .NET Core, donc ce n'est pas bon pour moi. Si j'avais une méthode qui n'utilisait pas de paramètre générique, je pourrais demander à FakeItEasy de compter le nombre de fois que la méthode a été invoquée, et s'attendre à ce qu'elle ait été invoquée avec des arguments en plus de tester le appels attendus. C'est certainement une option, mais cela signifie que je dois créer une façade sur mon interface (comme une méthode d'extension ou un wrapper, je suppose) pour prendre des paramètres de type plutôt que des paramètres génériques, ce qui signifie que je perds le temps de pré-compilation avertissements que je reçois avec la contrainte de paramètre générique.

La question réelle

Comment puis-je modifier mon test afin que je puisse affirmer qu'un appel inattendu a été pas fait avec tous les paramètres génériques autres que ceux que je m'y attendais en utilisant .NET de base/FakeItEasy/xUnit?

Répondre

3

Je suis peut-être trop simpliste, mais on dirait qu'un Strict Fake peut vous aider. En faire un, puis autoriser explicitement les appels que vous voulez.

//Arrange 
ICustomContainer fake = A.Fake<ICustomContainer>(x => x.Strict()); 

// allow just the registrations you want to 
A.CallTo(() => fake.Register<IMyInterface, IMyImplementation>()).DoesNothing(); 

Foo objectUnderTest = new Foo(fake); 

//Act 
objectUnderTest.Bar(); 

//Assert 
A.CallTo(() => fake.Register<IMyInterface, IMyImplementation>()).MustHaveHappened(); 
+0

Non, vous ne simplifiez pas trop; Je ne savais pas que tu pouvais le faire et après l'avoir essayé, ça semblait être exactement ce que je cherchais. Très bonne réponse! – Jay

+1

Je suis content d'avoir été utile. –