2016-05-04 10 views
1

Ich habe eine Konsole App, wo der Benutzer eine Nummer eingibt, und ich eine Funktion entsprechend dieser Nummer generieren. Ich habe Ninject.Extensions.Factory dafür verwendet, hier sind die Bindungen:C# - Komponententest, Mock und Ninjel Fabrik Erweiterung

Bind<IFeature>().To<FirstFeature>().Named("1"); 
    Bind<IFeature>().To<SecondFeature>().Named("2"); 
    Bind<IFeature>().To<ThirdFeature>().Named("3"); 
    Bind<IFeatureFactory>().ToFactory(() => new UseFirstArgumentAsNameInstanceProvider()); 

Der Code, den ich testen möchten, ist:

Konstruktor:

public FeatureService(IFeatureFactory featureFactory, IUILayer uiHandler, int howManyFeatures) 
    { 
     this.featureFactory = featureFactory; 
     this.uiHandler = uiHandler; 
     this.howManyFeatures = howManyFeatures; 
    } 

Methode im Test:

public async Task startService() 
    { 
     bool isBadInput = false; 
     string userSelection = null; 
     uiHandler.displayMenu(howManyFeatures); 
     userSelection = uiHandler.getSelection(); 
     while (!userSelection.Equals((howManyFeatures+1).ToString())) 
     { 
      IFeature feature = null; 
      try 
      { 
       feature = featureFactory.createFeature(userSelection); 
       isBadInput = false; 
      } 
      catch (ActivationException ex) 
      { 
       uiHandler.displayErrorMessage(); 
       isBadInput = true; 
      } 
      if (!isBadInput) 
      { 
       await feature.execFeature(); 
      } 
      uiHandler.displayMenu(howManyFeatures); 
      userSelection = uiHandler.getSelection(); 
     } 
    } 

Wie Sie sehen können, wenn ich try-createFeature, catch ich die ActivationException, was bedeutet, dass die Benutzereingabe ungültige Auswahl hat (ninject nicht die konkrete Klasse zu erhalten), und execFeature wird nicht aufgerufen.

Ich versuche, einen Komponententest zu schreiben, um zu testen, dass , wenn ein Benutzer eine gültige Auswahl eingibt, die Methode execFeature genannt wird. Hier

ist der Test:

[TestMethod] 
    public void WhenUserEnterValidSelectionExecFeatureCalled() 
    { 
     //Arrange 
     Mock<IFeature> featureMock = new Mock<IFeature>(); 
     Mock<IConsoleService> consoleServiceMock = new Mock<IConsoleService>(); 
     // mock user input 7 
     consoleServiceMock.Setup(c => c.ReadLine()).Returns("7"); 
     IUILayer uiLayer = new ConsoleUILayer(consoleServiceMock.Object); 
     Mock<IFeatureFactory> featureFactory = new Mock<IFeatureFactory>(); 
     featureMock.Setup(t => t.execFeature()); 
     featureFactory.Setup(t => t.createFeature(It.IsAny<string>())).Returns(featureMock.Object); 
     // init FeatureService with 3 features 
     IFeatureService featureService = new FeatureService(featureFactory.Object, uiLayer, 3); 

     //Act 
     featureService.startService(); 

     //Assert 
     featureMock.Verify(t => t.execFeature()); 
    } 

Wie Sie sehen können - ich eine Schaffung eines consoleMock mit Benutzereingabe von "7", und wenn ich die FeatureService schaffen habe ich in der howManyFeatures - Test sollte fehlschlagen (keine konkrete Umsetzung).

Jetzt, wenn ich mein Programm normal laufen lasse - wenn ich "7" eingib, verhält sich das Programm wie erwartet und gibt eine Fehlermeldung aus.

Wenn ich den Test ausführen, jede Eingabe in den consoleMock neben den HowManyFeatures + 1 hat den Test bestanden (HowManyFeatures +1 schlägt fehl, weil es nicht in die while gehen wird), und es sollte nicht so sein - es sollte für die Anzahl fehlschlagen die keine konkrete IFeature Implementierung haben (nur 1, 2 und 3 haben konkrete Implementierungen).

Wie löse ich das? Soll ich das Ninject Bindings in das Tests Projekt "bringen"? soll ich diese Methode überhaupt testen? oder alles ist nutzlos?

Alle Gedanken sind

geschätzt

Antwort

0

Sie müssen auf Ihren Test nicht bringen ninject Bindung, Ihre FeatureService braucht nicht zu wissen, dass Ihr IFeatureFactory auf ninject Bindung basiert und es darüber kümmert sich nicht darum.
Was Sie tun müssen, ist Ihr IFeatureFacotory Mock-Setup richtig, jetzt Ihr Mock kehrt die gleiche iFeature egal, was die Eingabe ist, weil diese das Verhalten ist, dass Sie es gesagt verwenden, um dies tun:

featureFactory.Setup(t => t.createFeature(It.IsAny<string>())).Returns(featureMock.Object); 

Wenn Sie will, dass es Activation werfen wird, wenn die Anzahl größer als 3 nur Setup wird das gewünschte Verhalten statt:

featureFactory.Setup(t => t.createFeature(It.Is<string>(input => (int)input>3))).Throws(new ActivationException()); 

Durch die Art und Weise sollten Sie vielleicht Ihren IUiLayer gerade verspotten und injizieren sie den FeatureService stattdessen Ihre consoleService von spöttischen und es verwenden, In Ihrer echten UiLayer-Implementierung wird es dies tun Machen Sie Ihre Tests viel einfacher.