2017-01-23 3 views
0

Ich weiß, dass ich ein Objekt neu kann und gebe es in aber ich versuche, die Syntax und Muster zu entsprechen, da der Wert eigentlich nie verwendet.Moq - Methode Auswertung mit Nullable-Parameter wirft null Ausnahme

Umsetzung:

public interface IDemoProvider 
{ 
    string GetStringById(int? id); 
} 

public interface IDemoService 
{ 
    bool Validate(ServiceRequest request); 
} 

public class ServiceRequest 
{ 
    public string foo { get; set; } 
    public int? bar { get; set; } 
} 

public class SomeDemoProvider : IDemoProvider 
{ 
    public virtual string GetStringById(int? id) 
    { 
     if (id != null) 
      return "success"; 
     else 
      return "else"; 
    } 
} 

public class BaseDemoService : IDemoService 
{ 
    public IDemoProvider Provider { get; set; } 

    public virtual bool Validate(ServiceRequest request) 
    { 
     if (request.bar == null) 
      return false; 

     return true; 
    } 
} 

public class SomeDemoService : BaseDemoService 
{ 
    public SomeDemoService(IDemoProvider provider) 
    { 
     Provider = provider; 
    } 

    public virtual string Post(ServiceRequest request) 
    { 
     if (!Validate(request)) 
      throw new Exception("Invalid Request"); 
     return Provider.GetStringById(request.bar); 
    } 
} 

Testcode:

[TestFixture] 
public class ProgramTests 
{ 
    [Test] 
    public void SomeDemoServiceTest() 
    { 
     var mockProvider = new Mock<IDemoProvider>(); 
     mockProvider.Setup(p => p.GetStringById(It.IsAny<int?>())).Returns(() => "success"); 

     object[] args = { mockProvider.Object }; 

     var mockService = new Mock<SomeDemoService>(args) {CallBase = true}; 
     mockService.Setup(s => s.Validate(It.IsAny<ServiceRequest>())).Returns(true); 

     string result = mockService.Object.Post(It.IsAny<ServiceRequest>()); 

     Assert.AreEqual("success", result); 
    } 
} 

Ausgabe

Dieses in einem NullReferenceException führt, die Sinn macht, da es versucht,zu lösenwährend der Ausführung, die auf Anforderungsebene null ist.

Wenn ich jedoch den Parameter mit null ersetzen, es funktioniert gut:

return Provider.GetStringById(null); 

hier Meine Frage ist, ob eine Möglichkeit gibt es die Abfangjäger zu machen erkennen, bevor die Expression der Bewertung, dass es sollte nur den Wert zurückgeben statt zu versuchen, den Ausdruck zu bewerten.

Ich kann den Rest des Request-Objekts verspotten, aber es scheint dumm, da die Werte nie verwendet werden, nach dem Test. Die wirkliche Frage hier ist, ob ich den Code oder den Test anders schreiben sollte, um dieses Szenario zu vermeiden, oder wenn ich ein Problem mit einem einfachen Workaround verkompliziere.

+3

Die Auswertung geschieht * vor * das Verfahren überhaupt aufgerufen wird. Also - nein, es ist nicht möglich, das ohne eine * ernsthafte * Vorverarbeitung Ihrer Bibliotheken zu haben. Ihr Code in "Post" sollte den Fall behandeln, in dem "request" null ist. Wenn es ungültig ist, dass "request" null ist, dann ist Ihr Test ungültig (es sollte ein Test sein, der behauptet, dass es ungültig ist, eine Null-Anfrage zu bestehen).Dies ist ein XY-Problem - und zum Glück für Sie - zeigt dieses Verhalten entweder einen Fehler in Ihrem Code oder ein Missverständnis dessen, was Sie testen – Rob

+0

Ich nehme auch an, "GetStoreByStoreReferenceId" sollte "GetObjectById" sein? – Rob

+2

Sie müssen diese Frage neu schreiben. In seiner jetzigen Form ist es unklar. Stellen Sie eine [mcve] zur Verfügung, mit der das Problem neu erstellt werden kann. – Nkosi

Antwort

0

Sie es falsch testen ist.

Wenn Sie die Methode im Test auszuüben versuchen falsch dann diese Linie ...

string result = mockService.Object.Post(It.IsAny<ServiceRequest>()); 

verwendet wird. Sie würden It.IsAny<ServiceRequest>() als Teil des Setups verwenden. Im Fall von, wie Sie es verwenden möchten, wird es in null im Validate Methode

request.bar == null 

führen, da der It.IsAny Ausdruck ist eigentlich nichts in die Methode übergeben.

Lesen Sie, wie Moq über die Moq Quickstart verwenden, um ein besseres Verständnis dafür zu bekommen, wie es zu verwenden, wenn die Prüfung.

den Test Rewrite als

public void SomeDemoServiceTest() { 
    //Arrange 
    var mockProvider = new Mock<IDemoProvider>(); 
    mockProvider.Setup(p => p.GetStringById(It.IsAny<int?>())).Returns(() => "success"); 

    var mockService = new Mock<SomeDemoService>(mockProvider.Object) { CallBase = true }; 
    mockService.Setup(s => s.Validate(It.IsAny<ServiceRequest>())).Returns(true); 

    var request = new ServiceRequest(); 

    //Act 
    var result = mockService.Object.Post(request); 

    //Assert 
    Assert.AreEqual("success", result); 
} 

Und sollte der Test.

+0

_Sie würden It.IsAny () als Teil des Setups verwenden. In dem Fall, wie Sie versuchen, es zu verwenden, wird es in der Validate-Methode null ergeben. Dies ist genau das, was ich vermisste. Ich las ein paar Tutorials durch und sah mir einige Videos an, aber es schien, als würden sie sich über all die Dinge lustig machen, also war es ein schlechtes Beispiel, dem ich folgen sollte. Danke @ Nkosi – xzist

-2

bitte überprüfen, ob Ihr request.SubProperty null ist oder nicht sein kann, es ist der Grund der Objektreferenz null

 if(request.SubProperty !=null) 
     { 
      var result = SomeProvider.GetObjectById(request.SubProperty.Id); 
     } 
Verwandte Themen