Freigeben über


Iteration 5 – Erstellen von Komponententests (C#)

von Microsoft

Code herunterladen

In der fünften Iteration vereinfachen wir die Wartung und Änderung unserer Anwendung, indem wir Komponententests hinzufügen. Wir simulieren unsere Datenmodellklassen und erstellen Komponententests für unsere Controller und die Validierungslogik.

Erstellen einer Kontaktverwaltung ASP.NET MVC-Anwendung (C#)

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 Personenliste speichern.

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

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

  • Iteration Nr. 2: Sorgen Sie dafür, dass die Anwendung gut aussieht. In dieser Iteration verbessern wir das Erscheinungsbild der Anwendung, indem wir die Standardansicht ASP.NET MVC master Seite und cascading Stylesheet ändern.

  • Iteration Nr. 3: Hinzufügen der Formularvalidierung In der dritten Iteration fügen wir eine 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 Nr. 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 Dependency Injection-Muster verwendet.

  • Iteration 5: Erstellen von Komponententests. In der fünften Iteration vereinfachen wir die Wartung und Änderung unserer Anwendung, indem wir Komponententests hinzufügen. 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 Ajax-Unterstützung 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 vereinfachen. 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 Contact Manager lose gekoppelt haben, haben wir die Anwendung widerstandsfähiger für Änderungen 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 erwiesene Wahrheit beim Schreiben von Code ist, dass jedes Mal, wenn Sie Code berühren, das Risiko der Einführung neuer Fehler entsteht.

An einem guten Tag kann Ihr Vorgesetzter Sie beispielsweise bitten, 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 das Risiko, dass funktionen, die zuvor funktioniert haben, nicht mehr funktionieren.

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 den Code in einer Ebene jedoch 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 Anwendungsschichten. 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 resilienter gegenüber Änderungen.

In dieser Iteration fügen wir komponententests zu unserer Contact Manager-Anwendung hinzu. Auf diese Weise können wir in der nächsten Iteration Kontaktgruppen zu unserer Anwendung hinzufügen, ohne sich Gedanken über den Bruch vorhandener Funktionen machen zu müssen.

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 Ihr gesamter 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 sammeln. Wenn die Ausführung der Komponententests sehr lange dauert, vermeiden Sie die Ausführung. Anders ausgedrückt: Komponententests mit langer Ausführungsdauer sind für die tägliche Programmierung 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 Modelldatenbank interagiert (weiter unten wird das Simulieren 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 einrichten. Da das Einrichten 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 erwägen, die Logik in Hilfsmethoden zu verschieben. Sie können Komponententests für Hilfsmethoden schreiben, die ausgeführt werden, ohne einen Webserver zu starten.

Hinweis

Während das Schreiben von Tests für Datenzugriffslogik oder Sichtlogik keine gute Idee beim Schreiben von Komponententests ist, können diese Tests beim Erstellen von Funktions- oder Integrationstests sehr nützlich 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 ein Mock Object-Framework nutzen. 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 Modellversion Ihrer Repositoryklasse zu generieren. Auf diese Weise können Sie die Modellrepositoryklasse anstelle der echten Repositoryklasse in Ihren Komponententests verwenden. Mithilfe des Pseudorepositorys können Sie die Ausführung von Datenbankcode beim Ausführen eines Komponententests vermeiden.

Visual Studio enthält kein Mock Object-Framework. Für .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 entpacken, stellen Sie sicher, dass Sie mit der rechten Maustaste auf die Datei klicken und auf die Schaltfläche Mit der Bezeichnung Blockierung aufheben klicken (siehe Abbildung 1).
  3. Entzippen Sie den Download.
  4. Fügen Sie einen Verweis auf die Moq-Assembly hinzu, indem Sie im Projekt ContactManager.Tests mit der rechten Maustaste auf den Ordner Verweise klicken und Verweis hinzufügen auswählen. Navigieren Sie auf der Registerkarte Durchsuchen zu dem Ordner, in dem Sie Moq entpackt haben, und wählen Sie die Moq.dll-Assembly aus. Klicken Sie auf die Schaltfläche OK .
  5. Nachdem Sie diese Schritte ausgeführt haben, sollte Der Ordner Verweise wie in Abbildung 2 aussehen.

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 Sie hier, 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 der Contact Manager-Anwendung. Wir verwenden diese Tests, um unsere Validierungslogik zu überprüfen.

Erstellen Sie im Projekt ContactManager.Tests einen neuen Ordner namens Models. Klicken Sie als Nächstes mit der rechten Maustaste auf den Ordner Modelle, und wählen Sie Hinzufügen, Neuer Test aus. Das In Abbildung 3 gezeigte Dialogfeld Neuen Test hinzufügen wird angezeigt. Wählen Sie die Vorlage Komponententest aus, und nennen Sie den neuen Test ContactManagerServiceTest.cs. Klicken Sie auf die Schaltfläche OK , um Den neuen Test zu 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 eine Fehlermeldung zum Modellzustand 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.

Der erste Test überprüft, ob ein gültiger Kontakt keinen Validierungsfehler generiert. Die verbleibenden Tests überprüfen die einzelnen Validierungsregeln.

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

Auflistung 1: Models\ContactManagerServiceTest.cs

using System.Web.Mvc;
using ContactManager.Models;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;

namespace ContactManager.Tests.Models
{
    [TestClass]
    public class ContactManagerServiceTest
    {
        private Mock<IContactManagerRepository> _mockRepository;
        private ModelStateDictionary _modelState;
        private IContactManagerService _service;

        [TestInitialize]
        public void Initialize()
        {
            _mockRepository = new Mock<IContactManagerRepository>();
            _modelState = new ModelStateDictionary();
            _service = new ContactManagerService(new ModelStateWrapper(_modelState), _mockRepository.Object);
        }

        [TestMethod]
        public void CreateContact()
        {
            // Arrange
            var contact = Contact.CreateContact(-1, "Stephen", "Walther", "555-5555", "steve@somewhere.com");

            // Act
            var result = _service.CreateContact(contact);
        
            // Assert
            Assert.IsTrue(result);
        }

        [TestMethod]
        public void CreateContactRequiredFirstName()
        {
            // Arrange
            var contact = Contact.CreateContact(-1, string.Empty, "Walther", "555-5555", "steve@somewhere.com");

            // Act
            var result = _service.CreateContact(contact);

            // Assert
            Assert.IsFalse(result);
            var error = _modelState["FirstName"].Errors[0];
            Assert.AreEqual("First name is required.", error.ErrorMessage);
        }

        [TestMethod]
        public void CreateContactRequiredLastName()
        {
            // Arrange
            var contact = Contact.CreateContact(-1, "Stephen", string.Empty, "555-5555", "steve@somewhere.com");

            // Act
            var result = _service.CreateContact(contact);

            // Assert
            Assert.IsFalse(result);
            var error = _modelState["LastName"].Errors[0];
            Assert.AreEqual("Last name is required.", error.ErrorMessage);
        }

        [TestMethod]
        public void CreateContactInvalidPhone()
        {
            // Arrange
            var contact = Contact.CreateContact(-1, "Stephen", "Walther", "apple", "steve@somewhere.com");

            // Act
            var result = _service.CreateContact(contact);

            // Assert
            Assert.IsFalse(result);
            var error = _modelState["Phone"].Errors[0];
            Assert.AreEqual("Invalid phone number.", error.ErrorMessage);
        }

        [TestMethod]
        public void CreateContactInvalidEmail()
        {
            // Arrange
            var contact = Contact.CreateContact(-1, "Stephen", "Walther", "555-5555", "apple");

            // Act
            var result = _service.CreateContact(contact);

            // Assert
            Assert.IsFalse(result);
            var error = _modelState["Email"].Errors[0];
            Assert.AreEqual("Invalid email address.", error.ErrorMessage);
        }
    }
}

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 ergänzt wird. 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<IContactManagerRepository>();

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

Hinweis

Bei Verwendung des Moq-Frameworks wird zwischen _mockRepository und _mockRepository.Object unterschieden. Erstere bezieht sich auf die Mock<IContactManagerRepository-Klasse> , die Methoden zum Angeben des Verhalten des Pseudorepositorys 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 eine instance der ContactManagerService-Klasse erstellt wird. Alle einzelnen Komponententests verwenden diese instance der ContactManagerService-Klasse.

Die Auflistung 1 enthält fünf Methoden, die den einzelnen Komponententests entsprechen. Jede dieser Methoden wird mit dem [TestMethod]-Attribut ergänzt. 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.

Der erste Komponententest mit dem Namen CreateContact() überprüft, ob der Aufruf von CreateContact() den Wert true zurückgibt, 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.

Bei den verbleibenden Tests wird überprüft, ob die CreateContact()-Methode mit einem ungültigen Contact aufgerufen wird, die Methode false zurückgibt und die erwartete Validierungsfehlermeldung dem Modellzustand 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 überprüft der Test, ob CreateContact() false zurückgibt und dieser 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. DIE NETMVC-Anwendung steuert 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 Create()-Methode des Kontaktcontrollers. Der erste Komponententest überprüft, dass die Create()-Methode an die Indexaktion umleitet, wenn ein gültiger Kontakt an die Create()-Methode übergeben wird. Anders ausgedrückt: 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. Daher simulieren wir die Dienstebene mit dem folgenden Code in der Initialize-Methode:

_service = new Mock();

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

_service.Expect(s => s.CreateContact(contact)).Returns(true);

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

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

_service.Expect(s => s.CreateContact(contact)).Returns(false);

Wenn sich die Create()-Methode erwartungsgemäß verhält, sollte die Create-Ansicht zurückgegeben werden, 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 Kontakteigenschaften zu korrigieren.

Wenn Sie Komponententests für Ihre Controller erstellen möchten, müssen Sie explizite Ansichtsnamen aus Ihren Controlleraktionen zurückgeben. Geben Sie beispielsweise keine Ansicht wie die folgende zurück:

return View();

Geben Sie stattdessen die Ansicht wie folgt zurück:

return View("Create");

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

Auflistung 2 : Controllers\ContactControllerTest.cs

using System.Web.Mvc;
using ContactManager.Controllers;
using ContactManager.Models;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;

namespace ContactManager.Tests.Controllers
{
    [TestClass]
    public class ContactControllerTest
    {
        private Mock<IContactManagerService> _service;

        [TestInitialize]
        public void Initialize()
        {
            _service = new Mock<IContactManagerService>();
        }

        [TestMethod]
        public void CreateValidContact()
        {
            // Arrange
            var contact = new Contact();
            _service.Expect(s => s.CreateContact(contact)).Returns(true);
            var controller = new ContactController(_service.Object);
        
            // Act
            var result = (RedirectToRouteResult)controller.Create(contact);

            // Assert
            Assert.AreEqual("Index", result.RouteValues["action"]);
        }

        [TestMethod]
        public void CreateInvalidContact()
        {
            // Arrange
            var contact = new Contact();
            _service.Expect(s => s.CreateContact(contact)).Returns(false);
            var controller = new ContactController(_service.Object);

            // Act
            var result = (ViewResult)controller.Create(contact);

            // Assert
            Assert.AreEqual("Create", result.ViewName);
        }

    }
}

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 die Anwendung weiterhin wie erwartet verhält. Die Komponententests dienen als Sicherheitsnetz für unsere Anwendung und ermöglichen es uns, 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 Dienstebene erstellt haben. Als Nächstes haben wir unsere Flusssteuerungslogik getestet, indem wir Komponententests für unsere Controllerebene erstellt haben. Beim Testen unserer Dienstebene haben wir unsere Tests für unsere Dienstebene von der Repositoryebene isoliert, indem wir unsere Repositoryebene simulieren. Beim Testen der Controllerebene haben wir unsere Tests für unsere Controllerebene isoliert, indem wir die Dienstebene simulieren.

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.