2016-11-13 3 views
1

Ich entwickle einen Chatbot in C# (basierend auf .NET Core), der modulares Verhalten hat. Eines der Verhaltensweisen, die ich entwickeln möchte, ist ein "admin" -Modul, das (neben anderen Funktionen) Administratoren erlauben soll, andere Verhaltensweisen dynamisch nach Namen zu aktivieren oder zu deaktivieren.Ist es möglich, den "Typnamen" eines Scheines in C# mit Moq zu verspotten?

Ich mag den Admin-Modul den Namen eines Verhalten zu bestimmen, durch seine Art info Inspektion und wie etwas zu tun:

var name = behaviour.GetType().GetTypeInfo().Name.Replace("Behaviour", string.Empty).ToLowerInvariant(); 

In einer BDD-Spezifikation ich zum ersten Mal hier schreibe, versuche ich bis zu setzen eine "Verhaltenskette", bestehend aus dem Admin-Modul (System im Test) und einem Scheinverhalten. Die Tests beinhalten das Senden von Befehlen, die dazu führen sollten, dass das Admin-Modul das Scheinverhalten aktiviert oder deaktiviert.

Das ist, was ich bisher getan habe:

public BehaviourIsEnabled() : base("Admin requests that a behaviour is enabled") 
{ 
    var mockTypeInfo = new Mock<TypeInfo>(); 
    mockTypeInfo.SetupGet(it => it.Name).Returns("MockBehaviour"); 

    var mockType = new Mock<Type>(); 
    mockType.Setup(it => it.GetTypeInfo()).Returns(mockTypeInfo.Object); 

    // TODO: make mock behaviour respond to "foo" 
    var mockBehaviour = new Mock<IMofichanBehaviour>(); 
    mockBehaviour.Setup(b => b.GetType()).Returns(mockType.Object); 

    this.Given(s => s.Given_Mofichan_is_configured_with_behaviour("administration"), AddBehaviourTemplate) 
     .Given(s => s.Given_Mofichan_is_configured_with_behaviour(mockBehaviour.Object), 
       "Given Mofichan is configured with a mock behaviour") 
      .And(s => s.Given_Mofichan_is_running()) 
     .When(s => s.When_I_request_that_a_behaviour_is_enabled("mock")) 
      .And(s => s.When_Mofichan_receives_a_message(this.JohnSmithUser, "foo")) 
     .Then(s => s.Then_the_mock_behaviour_should_have_been_triggered()) 
     .TearDownWith(s => s.TearDown()); 
} 

Das Problem, wenn ich laufen ist, dass GetTypeInfo() auf Type eine Erweiterung Methode ist, so wirft Moq die Ausnahme:

Expression Referenzen ein Verfahren, das auf das verspotteten Objekt nicht gehört: it => it.GetTypeInfo()

Eine Alternative, ich könnte einfach eine Name Eigenschaft zu IMofichanBehaviour hinzufügen, aber ich mag die Idee nicht, beliebige Methoden/Eigenschaften zu einem Produktionscode hinzuzufügen, der nur wirklich zum Vorteil des Testcodes da ist.

+0

die Erweiterungsmethode zeigen. Erweiterungsmethoden (statisch) erschweren es, Tests durchzuführen, abhängig von der Komplexität der Methode und auch der Tatsache, dass man zur Testbarkeit versuchen sollte, statische Klassen und Methoden zu vermeiden. – Nkosi

+0

@Nkosi Was meinen Sie mit der Erweiterungsmethode? Ich habe es in der Post gegeben: ['GetTypeInfo()'] (https://msdn.microsoft.com/en-us/library/system.reflection.introspectionextensions.gettypeinfo (v = vs.110) .aspx) . Sie haben Recht, dass Erweiterung/statische Methoden am besten vermieden werden, aber in diesem Fall habe ich nicht viel Auswahl, da es eine eingebaute ist, die ich verwenden muss, um Typinformationen in .NET Core zu überprüfen. – Tagc

+1

Verwenden Sie dann eine Fälschung, d. H .: 'öffentliche Klasse MockBehaviour: IMofichanBehaviour {...}' – Nkosi

Antwort

1

Halten Sie es einfach mit einer falschen Klasse, die erfüllt, was es verspottet wird.

public class MockBehaviour : IMofichanBehaviour { ... } 

Und Test würde dann folgendermaßen aussehen

public BehaviourIsEnabled() : base("Admin requests that a behaviour is enabled") { 

    // TODO: make mock behaviour respond to "foo" 
    var mockBehaviour = new MockBehaviour(); 


    this.Given(s => s.Given_Mofichan_is_configured_with_behaviour("administration"), AddBehaviourTemplate) 
     .Given(s => s.Given_Mofichan_is_configured_with_behaviour(mockBehaviour), 
       "Given Mofichan is configured with a mock behaviour") 
      .And(s => s.Given_Mofichan_is_running()) 
     .When(s => s.When_I_request_that_a_behaviour_is_enabled("mock")) 
      .And(s => s.When_Mofichan_receives_a_message(this.JohnSmithUser, "foo")) 
     .Then(s => s.Then_the_mock_behaviour_should_have_been_triggered()) 
     .TearDownWith(s => s.TearDown()); 
} 
+0

+1, das ist einfach, aber effektiv. Ich schäme mich, dass ich selbst nicht daran denke. Ich habe über die "Name/Id" Idee früher nachgedacht und ich bin tatsächlich diesen Weg gegangen, aber das ist ein guter Ansatz, den ich im Auge behalten sollte, wenn ich dieses Verhalten wieder brauche. Wird auch akzeptiert, es sei denn, jemand postet eine Möglichkeit, in Moq falsche Informationen einzugeben, was etwas bequemer, aber keineswegs unbedingt notwendig wäre. – Tagc

Verwandte Themen