2016-12-04 6 views
0

Dies ist mein erster Test der Einheit, und ich habe nur ein paar Fragen. Ich benutze in der Speicherdatenbank, um meine Dienstleistungen zu prüfen, und ich frage mich, ob ich es richtig mache. Meine erste Frage ist, brauche ich mehrere Assert auf alle meine Service-Anruf? wie brauche ich Assert für InsertProduct? Zweitens: Überprüfe ich dies, um bei jedem Serviceaufruf eine neue Instanz von Kontext zu verwenden?Benötige ich mehrere Asser? xUnit Test

Antwort

1

Ich würde Einwände gegen die Struktur Ihres Tests erheben. Sie verwenden nämlich den Service (Produktionscode), um die zugrunde liegende Datenbank vorzubereiten. Außerdem verwenden Sie den Produktionscode, um die Assertion zu erstellen.

Wenn ein Teil des Produktionscodes falsch ist, wird dieser Test fehlschlagen. Dieser Test soll jedoch sicherstellen, dass die Löschfunktion richtig ausgeführt wird.

Deshalb würde ich gesamten Test in der folgenden Weise umschreiben:

[Fact] 
public void ProductService_DeleteProduct_Test() 
{ 
    // arrange 
    var options = new DbContextOptionsBuilder<ApplicationDbContext>() 
     .UseInMemoryDatabase(databaseName: "ProductService_DeleteProduct_Test") 
     .Options; 

    var product = new Product() { Id = Guid.NewGuid(), Name = "Product"}; 

    // Insert object using other means, i.e. direct INSERT statement 

    // act 
    using (var context = new ApplicationDbContext(options)) 
    { 
     var service = new Service(context); 
     service.ProductService.DeleteProducts(new List<Guid> { product.Id }); 
    } 

    // assert 
    // Execute SELECT COUNT(*) instruction to fetch previously existing row 
    Assert.Equal(0, rowsCount); 
} 

Auf diese Weise werden Sie nur Produktionscode in dem wirkenden Teil des Tests berühren. Das ist der Teil, in dem Sie das Serviceobjekt verwenden, um ein Objekt aus der Datenbank zu löschen.

Die nachfolgende Assertion wird für einen Skalarwert count ausgeführt, der als Ergebnis einer unformatierten Anweisung SELECT abgerufen wird, die direkt auf dem Speicher ausgeführt wird.

Fazit ist, dass keiner der Teile Ihres Tests jetzt von der Korrektheit des Produktionscodes abhängt, außer der DeleteProducts Methode, die in der Tat die Methode im Test ist.

Und folglich ist die Antwort auf Ihre Frage, dass es nur eine Behauptung gibt, in diesem Test zu schreiben.

+0

eine weitere Frage bevor ich Ihre Frage akzeptiere, verwende ich Entity Framework, um meinen Test zu beheben, ich brauche 'context.Database.ExecuteSqlCommand' oder' context.Database.SqlQuery' oder sollte ich nur das 'using System verwenden. Data.SqlClient; ' – kram005

+0

Möglicherweise ja. Aber lassen Sie mich Ihnen sagen, dass ich in der Vergangenheit Testsuites hatte, in denen ich eine separate Verbindungszeichenfolge im Testprojekt hatte, und dann leere 'SqlCommands' verwendete, um Raw SQL auszuführen. Das entfernt sogar die letzte Verbindung zwischen Test und Produktionscode. Wie auch immer, das ist nur das Detail und Sie werden mit dem vorhandenen 'DbContext' arbeiten können. –

+0

Ich denke, ich muss mit dbcontext weitermachen, weil ich ef in der Speicherdatenbank verwende und ich weiß nicht, wie man in der Speicherdatenbank mit sqlcommand vorgeht – kram005

1

Beantworten Sie Ihre erste Frage, ich würde Nein sagen. Da dies ein Komponententest ist, testen Sie das Löschen speziell. Ich betrachte den Insert-Teil des Setups, da Sie das System in einen Zustand bringen, in dem Sie das Löschen testen möchten. Zu Zoran Horvats Standpunkt, wenn Sie können, eine Zeile in die Datenbank über andere Mittel als den Dienst selbst setzen.

Um Ihre zweite Frage zu beantworten, scheint es unnötig, drei Blöcke zu verwenden, in denen Sie den Dienst dreimal neu einrichten. Ich würde die Einfügung, die Löschung und die Assertion in dieselbe Verwendung einfügen und dabei eine Instanz des SUT oder Dienstes verwenden.

Wenn Sie jedoch mehrere Tests haben, die alle eine Zeile in der Datenbank erfordern, sollten Sie die Einfügung in eine SetUp-Methode mit dem [SetUp] -Attribut verschieben, das jeder Test zuvor aufrufen kann. In diesem Fall würden Sie mehrere Instanzen des Kontexts verwenden.

Verwandte Themen