Freigeben über


Iteration 5 – Erstellen von Komponententests (VB)

von Microsoft

Code herunterladen

In der fünften Iteration erleichtern wir die Wartung und Änderung unserer Anwendung durch Hinzufügen von Komponententests. Wir simulieren unsere Datenmodellklassen und erstellen Komponententests für unsere Controller und die Validierungslogik.

Erstellen einer Kontaktverwaltung ASP.NET MVC-Anwendung (VB)

In dieser Reihe von Tutorials erstellen wir eine gesamte Kontaktverwaltungsanwendung von Anfang bis Ende. Mit der Contact Manager-Anwendung können Sie Kontaktinformationen – Namen, Telefonnummern und E-Mail-Adressen – für eine Liste von Personen speichern.

Wir erstellen die Anwendung über mehrere Iterationen. Mit jeder Iteration verbessern wir die Anwendung schrittweise. Das Ziel dieses Ansatzes für mehrere Iterationen besteht darin, ihnen zu ermöglichen, den Grund für jede Änderung zu verstehen.

  • Iteration #1: Erstellen Sie die Anwendung. In der ersten Iteration erstellen wir den Contact Manager auf einfachste Weise. Wir fügen Unterstützung für grundlegende Datenbankvorgänge hinzu: Erstellen, Lesen, Aktualisieren und Löschen (CRUD).

  • Iteration #2: Lassen Sie die Anwendung schön aussehen. In dieser Iteration verbessern wir das Erscheinungsbild der Anwendung, indem wir die Standardansicht ASP.NET MVC master Seite und cascading Stylesheet ändern.

  • Iteration #3: Hinzufügen der Formularüberprüfung. In der dritten Iteration fügen wir die grundlegende Formularüberprüfung hinzu. Wir verhindern, dass Personen ein Formular einreichen, ohne die erforderlichen Formularfelder ausfüllen zu müssen. Außerdem überprüfen wir E-Mail-Adressen und Telefonnummern.

  • Iteration #4: Machen Sie die Anwendung lose gekoppelt. In dieser vierten Iteration nutzen wir mehrere Softwareentwurfsmuster, um die Verwaltung und Änderung der Contact Manager-Anwendung zu vereinfachen. Beispielsweise umgestalten wir unsere Anwendung so, dass sie das Repositorymuster und das Abhängigkeitsinjektionsmuster verwendet.

  • Iteration #5: Erstellen von Komponententests. In der fünften Iteration erleichtern wir die Wartung und Änderung unserer Anwendung durch Hinzufügen von Komponententests. Wir simulieren unsere Datenmodellklassen und erstellen Komponententests für unsere Controller und die Validierungslogik.

  • Iteration #6: Verwenden Sie die testgesteuerte Entwicklung. In dieser sechsten Iteration fügen wir unserer Anwendung neue Funktionen hinzu, indem wir zuerst Komponententests schreiben und Code für die Komponententests schreiben. In dieser Iteration fügen wir Kontaktgruppen hinzu.

  • Iteration #7: Hinzufügen von Ajax-Funktionen. In der siebten Iteration verbessern wir die Reaktionsfähigkeit und Leistung unserer Anwendung, indem wir Unterstützung für Ajax hinzufügen.

Diese Iteration

In der vorherigen Iteration der Contact Manager-Anwendung haben wir die Anwendung so umgestaltet, dass sie lose gekoppelt ist. Wir haben die Anwendung in verschiedene Controller-, Dienst- und Repositoryebenen unterteilt. Jede Ebene interagiert über Schnittstellen mit der darunter liegenden Ebene.

Wir haben die Anwendung umgestaltet, um die Verwaltung und Änderung der Anwendung zu erleichtern. Wenn wir beispielsweise eine neue Datenzugriffstechnologie verwenden müssen, können wir einfach die Repositoryebene ändern, ohne den Controller oder die Dienstebene zu berühren. Indem wir den Kontakt-Manager lose gekoppelt haben, haben wir die Anwendung gegenüber Änderungen widerstandsfähiger gemacht.

Aber was geschieht, wenn wir der Contact Manager-Anwendung ein neues Feature hinzufügen müssen? Oder was geschieht, wenn wir einen Fehler beheben? Eine traurige, aber gut bewährte Wahrheit des Schreibens von Code ist, dass bei jeder Berührung von Code das Risiko entsteht, neue Fehler einzuführen.

An einem schönen Tag kann Ihr Vorgesetzter Sie beispielsweise auffordern, dem Kontakt-Manager ein neues Feature hinzuzufügen. Sie möchte, dass Sie Support für Kontaktgruppen hinzufügen. Sie möchte, dass Sie Es Benutzern ermöglichen, ihre Kontakte in Gruppen wie Freunde, Unternehmen usw. zu organisieren.

Um dieses neue Feature zu implementieren, müssen Sie alle drei Ebenen der Contact Manager-Anwendung ändern. Sie müssen den Controllern, der Dienstebene und dem Repository neue Funktionen hinzufügen. Sobald Sie mit dem Ändern von Code beginnen, besteht die Gefahr, dass Funktionen, die zuvor funktioniert haben, beschädigt werden.

Das Umgestalten unserer Anwendung in separate Ebenen wie in der vorherigen Iteration war eine gute Sache. Dies war eine gute Sache, da es uns ermöglicht, Änderungen an ganzen Ebenen vorzunehmen, ohne den Rest der Anwendung zu berühren. Wenn Sie jedoch den Code innerhalb einer Ebene einfacher verwalten und ändern möchten, müssen Sie Komponententests für den Code erstellen.

Sie verwenden einen Komponententest, um eine einzelne Codeeinheit zu testen. Diese Codeeinheiten sind kleiner als ganze Anwendungsebenen. In der Regel verwenden Sie einen Komponententest, um zu überprüfen, ob sich eine bestimmte Methode in Ihrem Code wie erwartet verhält. Beispielsweise erstellen Sie einen Komponententest für die CreateContact()-Methode, die von der ContactManagerService-Klasse verfügbar gemacht wird.

Die Komponententests für eine Anwendung funktionieren wie ein Sicherheitsnetz. Wenn Sie Code in einer Anwendung ändern, können Sie eine Reihe von Komponententests ausführen, um zu überprüfen, ob die Änderung vorhandene Funktionen unterbricht. Komponententests sorgen dafür, dass Ihr Code sicher geändert werden kann. Komponententests machen den gesamten Code in Ihrer Anwendung widerstandsfähiger für Änderungen.

In dieser Iteration fügen wir unserer Contact Manager-Anwendung Komponententests hinzu. Auf diese Weise können wir in der nächsten Iteration Kontaktgruppen zu unserer Anwendung hinzufügen, ohne dass wir uns Gedanken darüber machen müssen, dass vorhandene Funktionen beschädigt werden.

Hinweis

Es gibt eine Vielzahl von Komponententestframeworks, einschließlich NUnit, xUnit.net und MbUnit. In diesem Tutorial verwenden wir das Komponententestframework, das in Visual Studio enthalten ist. Sie können jedoch genauso einfach eines dieser alternativen Frameworks verwenden.

Was getestet wird

In der perfekten Welt würde Der gesamte Code durch Komponententests abgedeckt. In der perfekten Welt hätten Sie das perfekte Sicherheitsnetz. Sie könnten jede Codezeile in Ihrer Anwendung ändern und sofort wissen, indem Sie Ihre Komponententests ausführen, ob durch die Änderung vorhandene Funktionen unterbrochen wurden.

Wir leben jedoch nicht in einer perfekten Welt. In der Praxis konzentrieren Sie sich beim Schreiben von Komponententests auf das Schreiben von Tests für Ihre Geschäftslogik (z. B. Validierungslogik). Insbesondere schreiben Sie keine Komponententests für Ihre Datenzugriffslogik oder Ihre Ansichtslogik.

Um nützlich zu sein, müssen Komponententests sehr schnell ausgeführt werden. Sie können problemlos Hunderte (oder sogar Tausende) von Komponententests für eine Anwendung ansammeln. Wenn die Ausführung der Komponententests lange dauert, vermeiden Sie die Ausführung. Mit anderen Worten, lange Komponententests sind für alltägliche Codierungszwecke nutzlos.

Aus diesem Grund schreiben Sie in der Regel keine Komponententests für Code, der mit einer Datenbank interagiert. Das Ausführen von Hunderten von Komponententests für eine Livedatenbank wäre zu langsam. Stattdessen simulieren Sie Ihre Datenbank und schreiben Code, der mit der Mockdatenbank interagiert (unten wird die Simulation einer Datenbank erläutert).

Aus einem ähnlichen Grund schreiben Sie in der Regel keine Komponententests für Ansichten. Um eine Ansicht zu testen, müssen Sie einen Webserver starten. Da das Hochsenden eines Webservers ein relativ langsamer Prozess ist, wird das Erstellen von Komponententests für Ihre Ansichten nicht empfohlen.

Wenn Ihre Ansicht komplizierte Logik enthält, sollten Sie die Logik in Hilfsmethoden verschieben. Sie können Komponententests für Hilfsmethoden schreiben, die ausgeführt werden, ohne einen Webserver zu starten.

Hinweis

Das Schreiben von Tests für Datenzugriffslogik oder Sichtlogik ist beim Schreiben von Komponententests zwar keine gute Idee, aber diese Tests können beim Erstellen von Funktions- oder Integrationstests sehr wertvoll sein.

Hinweis

ASP.NET MVC ist die Web Forms Ansichts-Engine. Während die Web Forms Ansichts-Engine von einem Webserver abhängig ist, sind andere Ansichts-Engines möglicherweise nicht.

Verwenden eines Mock Object Frameworks

Beim Erstellen von Komponententests müssen Sie fast immer von einem Mock Object-Framework profitieren. Mit einem Mock Object-Framework können Sie Mocks und Stubs für die Klassen in Ihrer Anwendung erstellen.

Sie können beispielsweise ein Mock Object-Framework verwenden, um eine Mockversion Ihrer Repositoryklasse zu generieren. Auf diese Weise können Sie die Pseudorepositoryklasse anstelle der echten Repositoryklasse in Ihren Komponententests verwenden. Mithilfe des Pseudorepositorys können Sie das Ausführen von Datenbankcode beim Ausführen eines Komponententests vermeiden.

Visual Studio enthält kein Mock Object-Framework. Für das .NET Framework stehen jedoch mehrere kommerzielle und Open Source Mock Object-Frameworks zur Verfügung:

  1. Moq: Dieses Framework ist unter der Open Source BSD-Lizenz verfügbar. Sie können Moq von https://code.google.com/p/moq/herunterladen.
  2. Rhino Mocks: Dieses Framework ist unter der Open Source BSD-Lizenz verfügbar. Sie können Rhino Mocks unter http://ayende.com/projects/rhino-mocks.aspxherunterladen.
  3. Typemock Isolator: Dies ist ein kommerzielles Framework. Sie können eine Testversion von http://www.typemock.com/herunterladen.

In diesem Tutorial habe ich mich für Moq entschieden. Sie können jedoch genauso einfach Rhino Mocks oder Typemock Isolator verwenden, um die Mock-Objekte für die Contact Manager-Anwendung zu erstellen.

Bevor Sie Moq verwenden können, müssen Sie die folgenden Schritte ausführen:

  1. .
  2. Bevor Sie den Download entzippen, stellen Sie sicher, dass Sie mit der rechten Maustaste auf die Datei klicken und dann auf die Schaltfläche Entsperren klicken (siehe Abbildung 1).
  3. Entzippen Sie den Download.
  4. Fügen Sie ihrem Testprojekt einen Verweis auf die Moq-Assembly hinzu, indem Sie die Menüoption Projekt, Verweis hinzufügen auswählen, um das Dialogfeld Verweis hinzufügen zu öffnen. Navigieren Sie auf der Registerkarte Durchsuchen zu dem Ordner, in dem Sie Moq entzippt haben, und wählen Sie die Moq.dll Assembly aus. Klicken Sie auf die Schaltfläche OK (siehe Abbildung 2).

Aufheben der Blockierung von Moq

Abbildung 01: Aufheben der Blockierung von Moq(Klicken Sie hier, um das Bild in voller Größe anzuzeigen)

Verweise nach dem Hinzufügen von Moq

Abbildung 02: Verweise nach dem Hinzufügen von Moq(Klicken, um das bild in voller Größe anzuzeigen)

Erstellen von Komponententests für die Dienstebene

Beginnen wir mit dem Erstellen einer Reihe von Komponententests für die Dienstebene unserer Contact Manager-Anwendung. Wir verwenden diese Tests, um unsere Validierungslogik zu überprüfen.

Erstellen Sie im Projekt ContactManager.Tests einen neuen Ordner mit dem Namen Models. Klicken Sie als Nächstes mit der rechten Maustaste auf den Ordner Modelle, und wählen Sie Hinzufügen, Neuer Test aus. Das Dialogfeld Neuen Test hinzufügen in Abbildung 3 wird angezeigt. Wählen Sie die Vorlage Komponententest aus, und nennen Sie Ihren neuen Test ContactManagerServiceTest.vb. Klicken Sie auf die Schaltfläche OK , um Ihren neuen Test ihrem Testprojekt hinzuzufügen.

Hinweis

Im Allgemeinen soll die Ordnerstruktur Ihres Testprojekts mit der Ordnerstruktur Ihres ASP.NET MVC-Projekts übereinstimmen. Beispielsweise platzieren Sie Controllertests in einem Ordner Controller, Modelltests in einem Ordner Models usw.

Models\ContactManagerServiceTest.cs

Abbildung 03: Models\ContactManagerServiceTest.cs(Klicken Sie hier, um das bild in voller Größe anzuzeigen)

Zunächst möchten wir die CreateContact()-Methode testen, die von der ContactManagerService-Klasse verfügbar gemacht wird. Wir erstellen die folgenden fünf Tests:

  • CreateContact() – Testet, dass CreateContact() den Wert true zurückgibt, wenn ein gültiger Contact an die -Methode übergeben wird.
  • CreateContactRequiredFirstName(): Testet, dass dem Modellzustand eine Fehlermeldung hinzugefügt wird, wenn ein Contact mit einem fehlenden Vornamen an die CreateContact()-Methode übergeben wird.
  • CreateContactRequiredLastName() – Testet, dass eine Fehlermeldung zum Modellzustand hinzugefügt wird, wenn ein Contact mit einem fehlenden Nachnamen an die CreateContact()-Methode übergeben wird.
  • CreateContactInvalidPhone() – Testet, dass eine Fehlermeldung zum Modellzustand hinzugefügt wird, wenn ein Kontakt mit einer ungültigen Telefonnummer an die CreateContact()-Methode übergeben wird.
  • CreateContactInvalidEmail() – Testet, dass eine Fehlermeldung zum Modellzustand hinzugefügt wird, wenn ein Kontakt mit einer ungültigen E-Mail-Adresse an die CreateContact()-Methode übergeben wird.

Beim ersten Test wird überprüft, ob ein gültiger Kontakt keinen Validierungsfehler generiert. Die restlichen Tests überprüfen die einzelnen Validierungsregeln.

Der Code für diese Tests ist in Listing 1 enthalten.

Eintrag 1 : Models\ContactManagerServiceTest.vb

Imports Microsoft.VisualStudio.TestTools.UnitTesting
Imports Moq
Imports System.Web.Mvc

<TestClass()> _
Public Class ContactManagerServiceTest

    Private _mockRepository As Mock(Of IContactManagerRepository)
    Private _modelState As ModelStateDictionary
    Private _service As IContactManagerService

    <TestInitialize()> _
    Public Sub Initialize()
        _mockRepository = New Mock(Of IContactManagerRepository)()
        _modelState = New ModelStateDictionary()
        _service = New ContactManagerService(new ModelStateWrapper(_modelState), _mockRepository.Object)
    End Sub

    <TestMethod()> _
    Public Sub CreateContact()
        ' Arrange
        Dim contactToCreate = Contact.CreateContact(-1, "Stephen", "Walther", "555-5555", "steve@somewhere.com")

        ' Act
        Dim result = _service.CreateContact(contactToCreate)

        ' Assert
        Assert.IsTrue(result)
    End Sub

    <TestMethod()> _
    Public Sub CreateContactRequiredFirstName()
        ' Arrange
        Dim contactToCreate = Contact.CreateContact(-1, String.Empty, "Walther", "555-5555", "steve@somewhere.com")

        ' Act
        Dim result = _service.CreateContact(contactToCreate)

        ' Assert
        Assert.IsFalse(result)
        Dim [error] = _modelState("FirstName").Errors(0)
        Assert.AreEqual("First name is required.", [error].ErrorMessage)
    End Sub

    <TestMethod()> _
    Public Sub CreateContactRequiredLastName()
        ' Arrange
        Dim contactToCreate = Contact.CreateContact(-1, "Stephen", String.Empty, "555-5555", "steve@somewhere.com")

        ' Act
        Dim result = _service.CreateContact(contactToCreate)

        ' Assert
        Assert.IsFalse(result)
        Dim [error] = _modelState("LastName").Errors(0)
        Assert.AreEqual("Last name is required.", [error].ErrorMessage)
    End Sub

    <TestMethod()> _
    Public Sub CreateContactInvalidPhone()
        ' Arrange
        Dim contactToCreate = Contact.CreateContact(-1, "Stephen", "Walther", "apple", "steve@somewhere.com")

        ' Act
        Dim result = _service.CreateContact(contactToCreate)

        ' Assert
        Assert.IsFalse(result)
        Dim [error] = _modelState("Phone").Errors(0)
        Assert.AreEqual("Invalid phone number.", [error].ErrorMessage)
    End Sub

    <TestMethod()> _
    Public Sub CreateContactInvalidEmail()
        ' Arrange
        Dim contactToCreate = Contact.CreateContact(-1, "Stephen", "Walther", "555-5555", "apple")

        ' Act
        Dim result = _service.CreateContact(contactToCreate)

        ' Assert
        Assert.IsFalse(result)
        Dim [error] = _modelState("Email").Errors(0)
        Assert.AreEqual("Invalid email address.", [error].ErrorMessage)
    End Sub
End Class

Da wir die Contact-Klasse in Listing 1 verwenden, müssen wir dem Testprojekt einen Verweis auf das Microsoft Entity Framework hinzufügen. Fügen Sie einen Verweis auf die System.Data.Entity-Assembly hinzu.

Listing 1 enthält eine Methode mit dem Namen Initialize(), die mit dem [TestInitialize]-Attribut versehen ist. Diese Methode wird automatisch aufgerufen, bevor die einzelnen Komponententests ausgeführt werden (sie wird 5 Mal direkt vor jedem Komponententest aufgerufen). Die Initialize()-Methode erstellt ein Pseudorepository mit der folgenden Codezeile:

_mockRepository = New Mock(Of IContactManagerRepository)()

Diese Codezeile verwendet das Moq-Framework, um ein Pseudorepository-Repository über die IContactManagerRepository-Schnittstelle zu generieren. Das Pseudorepository wird anstelle des tatsächlichen EntityContactManagerRepository verwendet, um den Zugriff auf die Datenbank zu vermeiden, wenn jeder Komponententest ausgeführt wird. Das Pseudorepository-Repository implementiert die Methoden der IContactManagerRepository-Schnittstelle, aber die Methoden tun nichts.

Hinweis

Bei Verwendung des Moq-Frameworks wird zwischen _mockRepository und _mockRepository.Object unterschieden. Ersteres bezieht sich auf die Mock(Of IContactManagerRepository)-Klasse, die Methoden zum Angeben des Verhalten des Mockrepository enthält. Letzteres bezieht sich auf das tatsächliche Pseudorepository-Repository, das die IContactManagerRepository-Schnittstelle implementiert.

Das Pseudorepository wird in der Initialize()-Methode verwendet, wenn ein instance der ContactManagerService-Klasse erstellt wird. Alle einzelnen Komponententests verwenden diese instance der ContactManagerService-Klasse.

List 1 enthält fünf Methoden, die den einzelnen Komponententests entsprechen. Jede dieser Methoden ist mit dem [TestMethod]-Attribut versehen. Wenn Sie die Komponententests ausführen, wird jede Methode aufgerufen, die über dieses Attribut verfügt. Anders ausgedrückt: Jede Methode, die mit dem [TestMethod]-Attribut versehen ist, ist ein Komponententest.

Beim ersten Komponententest mit dem Namen CreateContact() wird überprüft, ob beim Aufrufen von CreateContact() der Wert true zurückgegeben wird, wenn eine gültige instance der Contact-Klasse an die -Methode übergeben wird. Der Test erstellt eine instance der Contact-Klasse, ruft die CreateContact()-Methode auf und überprüft, ob CreateContact() den Wert true zurückgibt.

Die restlichen Tests überprüfen, ob die Methode CreateContact() mit einem ungültigen Contact aufgerufen wird, die Methode false zurückgibt und die erwartete Validierungsfehlermeldung dem Modellstatus hinzugefügt wird. Der CreateContactRequiredFirstName()-Test erstellt beispielsweise eine instance der Contact-Klasse mit einer leeren Zeichenfolge für die FirstName-Eigenschaft. Als Nächstes wird die CreateContact()-Methode mit dem ungültigen Contact aufgerufen. Schließlich wird im Test überprüft, ob CreateContact() false zurückgibt und dass der Modellzustand die erwartete Validierungsfehlermeldung "Vorname ist erforderlich" enthält.

Sie können die Komponententests in Listing 1 ausführen, indem Sie die Menüoption Test, Run, All Tests in Solution (STRG+R, A) auswählen. Die Ergebnisse der Tests werden im Fenster Testergebnisse angezeigt (siehe Abbildung 4).

Testergebnisse

Abbildung 04: Testergebnisse (Klicken Sie hier, um das bild in voller Größe anzuzeigen)

Erstellen von Komponententests für Controller

ASP.NET MVC-Anwendung steuern den Ablauf der Benutzerinteraktion. Beim Testen eines Controllers möchten Sie testen, ob der Controller das richtige Aktionsergebnis zurückgibt und Daten anzeigt. Sie können auch testen, ob ein Controller mit Modellklassen in der erwarteten Weise interagiert.

Beispielsweise enthält Listing 2 zwei Komponententests für die Contact controller Create()-Methode. Beim ersten Komponententest wird überprüft, dass die Create()-Methode, wenn ein gültiger Contact an die Create()-Methode übergeben wird, zur Indexaktion umgeleitet wird. Mit anderen Worten, wenn ein gültiger Contact übergeben wird, sollte die Create()-Methode ein RedirectToRouteResult zurückgeben, das die Indexaktion darstellt.

Wir möchten die ContactManager-Dienstebene nicht testen, wenn wir die Controllerebene testen. Aus diesem Grund simulieren wir die Dienstebene mit dem folgenden Code in der Initialize-Methode:

_service = New Mock(Of IContactManagerService)()

Im Komponententest CreateValidContact() wird das Verhalten des Aufrufens der CreateContact()-Methode auf Dienstebene mit der folgenden Codezeile simuliert:

_service.Expect( Function(s) s.CreateContact(contactToCreate) ).Returns(True)

Diese Codezeile bewirkt, dass der Mock-ContactManager-Dienst den Wert true zurückgibt, wenn seine CreateContact()-Methode aufgerufen wird. Durch Das Simulieren der Dienstebene können wir das Verhalten unseres Controllers testen, ohne Code in der Dienstebene ausführen zu müssen.

Beim zweiten Komponententest wird überprüft, ob die Create()-Aktion die Create-Ansicht zurückgibt, wenn ein ungültiger Kontakt an die -Methode übergeben wird. Wir verursachen, dass die CreateContact()-Methode der Dienstschicht den Wert false mit der folgenden Codezeile zurückgibt:

_service.Expect( Function(s) s.CreateContact(contactToCreate) ).Returns(False)

Wenn sich die Create()-Methode wie erwartet verhält, sollte sie die Create-Ansicht zurückgeben, wenn die Dienstebene den Wert false zurückgibt. Auf diese Weise kann der Controller die Validierungsfehlermeldungen in der Ansicht Erstellen anzeigen, und der Benutzer hat die Möglichkeit, diese ungültigen Contact-Eigenschaften zu korrigieren.

Wenn Sie Planen, Komponententests für Ihre Controller zu erstellen, müssen Sie explizite Ansichtsnamen aus Ihren Controlleraktionen zurückgeben. Geben Sie beispielsweise keine Ansicht wie folgt zurück:

Return View()

Geben Sie stattdessen die Ansicht wie folgt zurück:

Rückgabeansicht("Erstellen")

Wenn Sie beim Zurückgeben einer Ansicht nicht explizit sind, gibt die ViewResult.ViewName-Eigenschaft eine leere Zeichenfolge zurück.

Listing 2 – Controller\ContactControllerTest.vb

Imports Microsoft.VisualStudio.TestTools.UnitTesting
Imports Moq
Imports System.Web.Mvc

<TestClass()> _
Public Class ContactControllerTest

    Private _service As Mock(Of IContactManagerService)

    <TestInitialize()> _
    Public Sub Initialize()
        _service = New Mock(Of IContactManagerService)()
    End Sub

    <TestMethod()> _
    Public Sub CreateValidContact()
        ' Arrange
        Dim contactToCreate = New Contact()
        _service.Expect(Function(s) s.CreateContact(contactToCreate)).Returns(True)
        Dim controller = New ContactController(_service.Object)

        ' Act
        Dim result = CType(controller.Create(contactToCreate), RedirectToRouteResult)

        ' Assert
        Assert.AreEqual("Index", result.RouteValues("action"))
    End Sub

    <TestMethod()> _
    Public Sub CreateInvalidContact()
        ' Arrange
        Dim contactToCreate = New Contact()
        _service.Expect(Function(s) s.CreateContact(contactToCreate)).Returns(False)
        Dim controller = New ContactController(_service.Object)

        ' Act
        Dim result = CType(controller.Create(contactToCreate), ViewResult)

        ' Assert
        Assert.AreEqual("Create", result.ViewName)
    End Sub

End Class

Zusammenfassung

In dieser Iteration haben wir Komponententests für unsere Contact Manager-Anwendung erstellt. Wir können diese Komponententests jederzeit ausführen, um zu überprüfen, ob sich unsere Anwendung weiterhin wie erwartet verhält. Die Komponententests dienen als Sicherheitsnetz für unsere Anwendung, die es uns ermöglicht, unsere Anwendung in Zukunft sicher zu ändern.

Wir haben zwei Gruppen von Komponententests erstellt. Zunächst haben wir unsere Validierungslogik getestet, indem wir Komponententests für unsere Serviceebene erstellt haben. Als Nächstes haben wir unsere Ablaufsteuerungslogik getestet, indem wir Komponententests für unsere Controllerebene erstellt haben. Beim Testen unserer Serviceschicht isolierten wir unsere Tests für unsere Serviceschicht von unserer Repositoryebene, indem wir unsere Repositoryebene simulierten. Beim Testen der Controllerebene isolierten wir unsere Tests für unsere Controllerebene, indem wir die Dienstschicht simulierten.

In der nächsten Iteration ändern wir die Contact Manager-Anwendung so, dass sie Kontaktgruppen unterstützt. Wir fügen diese neue Funktionalität unserer Anwendung mithilfe eines Softwareentwurfsprozesses namens testgesteuerte Entwicklung hinzu.