{"id":459,"date":"2015-06-07T11:17:56","date_gmt":"2015-06-07T09:17:56","guid":{"rendered":"http:\/\/invidit.de\/blog\/?p=459"},"modified":"2015-07-04T14:36:37","modified_gmt":"2015-07-04T12:36:37","slug":"hoer-mal-wer-da-testet-net-edition","status":"publish","type":"post","link":"https:\/\/invidit.de\/blog\/hoer-mal-wer-da-testet-net-edition\/","title":{"rendered":"H\u00f6r mal wer da testet &#8211; .Net Edition"},"content":{"rendered":"<p>Hallo Spa\u00df Coder,<\/p>\n<p>in den letzten Artikeln <a href=\"http:\/\/invidit.de\/blog\/testautomatisierung\/\">Testautomatisierung<\/a>, <a href=\"http:\/\/invidit.de\/blog\/von-tests-und-komponenten\/\">Von Tests und Komponenten<\/a> sowie <a href=\"http:\/\/invidit.de\/blog\/kein-unit-test-wie-jeder-andere\/\">Kein Unit-Test wie jeder andere<\/a> haben wir euch hei\u00df darauf gemacht, euren Code automatisiert auf funktionale Richtigkeit hin zu \u00fcberpr\u00fcfen. In diesem Artikel m\u00f6chten wir euch ein paar Werkzeuge vorstellen, mit dessen Hilfe ihr euren .Net-Code automatisiert testen k\u00f6nnt. Wir setzen dabei wie immer C# als Sprache ein, die vorgestellten Werkzeuge funktionieren aber genauso gut mit VB.Net.<\/p>\n<p>F\u00fcr Werkzeuge, die ihr im Umfeld von Java verwenden k\u00f6nnt lest den Artikel <a href=\"http:\/\/invidit.de\/blog\/hoer-mal-wer-da-testet-java-edition\/\">H\u00f6r mal wer da testet &#8211; Java Edition<\/a>.<\/p>\n<p>Die hier verwendeten Beispiele testen eine Implementierung des Katas <a href=\"https:\/\/app.box.com\/s\/5ims8misf6z0uh1vut18\">Russische Bauernmultiplikation<\/a> aus dem Fundus der <a href=\"http:\/\/ccd-school.de\/coding-dojo\/\">Coding Dojos der CCD<\/a>.<\/p>\n<p>&nbsp;<\/p>\n<h1>NUnit<\/h1>\n<p>Mit Hilfe von NUnit k\u00f6nnen wir unseren Code einfach automatisch testen, ohne die Anwendung selbst starten zu m\u00fcssen. Wir k\u00f6nnen Test-Code schreiben und darin die Methoden unserer Klasse aufrufen. NUnit f\u00fchrt diese Tests dann aus und bietet auch eine M\u00f6glichkeit, die Ergebnisse zu pr\u00fcfen.<\/p>\n<p>Das Visual Studio bindet NUnit mit Hilfe eines Plugins, die seit der Version 2013 auch in der kostenlosen Community Edition des VS verwendet werden k\u00f6nnen. Die Tests lassen sich dann mit einem Klick starten und zeigen die Ergebnisse des Testaufrufs komfortabel an. So zeigt ein gr\u00fcner Balken, dass alle Tests erfolgreich durchlaufen wurden, ein roter, dass Tests fehlgeschlagen sind und ein gelber Balken zeigt an, dass Tests nicht ausgef\u00fchrt wurden. Bei fehlgeschlagenen Tests sehen wir dann, wo der Test fehlschl\u00e4gt und wir k\u00f6nnen uns sofort an die Behebung des Problems machen.<\/p>\n<h2>Beispiele:<\/h2>\n<p>Fangen wir mit einem einfachen Test an. Wir wollen testen, ob die Methode <em>Mul<\/em> 1\u00d71 rechnen kann. Wir erwarten, dass dabei das Ergebnis 1 herauskommt.<\/p>\n<pre class=\"lang:c# decode:true \">[Test]\r\npublic void OneTimesOneIsOne()\r\n{\r\n    IMultiplikation sut = new RussischeBauernmultiplikation();\r\n    Assert.AreEqual(1, sut.Mul(1, 1));\r\n}<\/pre>\n<p>Das Attribut<em> [Test]<\/em> kennzeichnet hier die Testmethode, wodurch NUnit diese Methode als ausf\u00fchrbaren Test erkennt. Als n\u00e4chstes erstellen wir eine Instanz unserer zu testenden Klasse <em>RussischeBauernmultiplikation. <\/em>Wir haben uns angew\u00f6hnt die zu testende Variable <em>sut<\/em> zu nennen, als Abk\u00fcrzung f\u00fcr <em><strong>S<\/strong>ystem <strong>U<\/strong>nder <strong>T<\/strong>est<\/em> oder <em><strong>S<\/strong>ubject <strong>U<\/strong>nder <strong>T<\/strong>est (siehe auch <a href=\"http:\/\/invidit.de\/blog\/von-tests-und-komponenten\/\">Von Tests und Komponenten<\/a>)<\/em>. Dadurch erkennen wir auch bei komplexeren Testmethoden sofort, welche Klasse was wir eigentlich testen.<br \/>\nIn der letzten Zeile wird nun gepr\u00fcft, durch unsere Behauptung (englisch: Assertion), dass 1\u00d71 = 1 ist. Der erste Parameter der Methode <em>AreEqual <\/em>ist dabei unser erwartetes Ergebnis (1) und der zweite Parameter das tats\u00e4chliche Ergebnis des Methodenaufrufs unserer Testklasse.<\/p>\n<p>Funktioniert der Test, zeigt NUnit einen gr\u00fcnen Balken an. Schl\u00e4gt der Test hingegen fehl, wird der Balken rot und NUnit zeigt uns an, welcher Test fehlgeschlagen ist. Hier eine beispielhafte Ausgabe von NUnit, wenn die Methode Mul(1, 1) statt der erwarteten 1 eine 2 zur\u00fcck gibt:<\/p>\n<blockquote><p>de.invidit.RussischeBauernmultiplikation.Test.RussischeBauernmultiplikationTests.OneTimesOneIsOne:<br \/>\nExpected: 1<br \/>\nBut was:\u00a0 2<br \/>\nbei de.invidit.RussischeBauernmultiplikation.Test.RussischeBauernmultiplikationTests.OneTimesOneIsOne() in \\RussischeBauernmultiplikation.Test\\RussischeBauernmultiplikationNUnit\\RussischeBauernmultiplikationTests.cs:Zeile 15.<\/p><\/blockquote>\n<p>Wir sehen also, dass der Aufruf in Zeile 15 der Test-Klasse <em>RussischeBauernmultiplikationTests<\/em> zu einem Fehler f\u00fchrt.<\/p>\n<p>Auch der Aufbau des Tests, wie wir ihn im Artikel\u00a0<a href=\"http:\/\/invidit.de\/blog\/von-tests-und-komponenten\/\">Von Tests und Komponenten<\/a> beschrieben haben ist hier erkennbar. Hier nochmal eine deutlichere Aufteilung am Beispiel des Tests 2\u00d72 = 4:<\/p>\n<pre class=\"lang:c# decode:true \">[Test]\r\npublic void TwoTimesOneIsTwo()\r\n{\r\n    \/\/ Initialisierung des Ausgangszustands\r\n    RussischeBauernmultiplikation sut = new RussischeBauernmultiplikation();\r\n    int expected = 4;\r\n\r\n    \/\/ Aufruf der zu testenden Methode\r\n    int actual = sut.Mul(2, 2);\r\n\r\n    \/\/ Pr\u00fcfung des Ergebnisses\r\n    Assert.AreEqual(expected, actual);\r\n}<\/pre>\n<p>Neben der zu testenden Klasse legen wir auch unser erwartetes Ergebnis in einer Variablen ab. Passend zum Parameternamen der assert-Methoden von NUnit nennen wir die Variable <em>expected. <\/em>Dann rufen wir unsere zu testende Methode auf, also <em>Mul <\/em>und speichern das Ergebnis in der Variable <em>actual<\/em>. Zum Schluss pr\u00fcfen wir die Behauptung (<em>assertion<\/em>), ob unsere Erwartung (<em>expected<\/em>) mit dem tats\u00e4chlichen (<em>actual<\/em>) Ergebnis \u00fcbereinstimmt.<\/p>\n<p>Auf diese Weise lassen sich die meisten Methoden einfach testen.<\/p>\n<h1>Microsoft Unit Testing Framework<\/h1>\n<p>Microsoft Unit Testing Framework funktioniert genauso wie NUnit und ist seit Version 2012 fester Bestandteil der kostenlosen Editionen des Visual Studios (VS Express und seit 2013 VS Community). Die Syntax unterscheidet sich von NUnit, die Einbindung in die IDE ist aber genauso gut (siehe oben bei der Beschreibung von NUnit).<\/p>\n<h2>Beispiele:<\/h2>\n<p>F\u00fcr den Test mit dem Microsoft Unit Testing Framework werden eigene Attribute zur Kennzeichnung von Testklasse und -methoden verwendet.<\/p>\n<pre class=\"lang:c# decode:true\">[TestMethod]\r\npublic void OneTimesOneIsOne()\r\n{\r\n\tIMultiplikation sut = new RussischeBauernmultiplikation();\r\n\tAssert.AreEqual(1, sut.Mul(1, 1));\r\n}<\/pre>\n<p>So ersetzen wir einfach das Attribute <em>[Test]<\/em> von NUnit durch <em>[TestMethod]<\/em>. Dazu lege ich ein MS-Test Projekt an, womit auch die erforderlichen Verweise korrekt vorhanden sind. \u00dcber das Men\u00fc <em>Test -&gt; Run -&gt; All Tests<\/em> lassen sich dann alle Test der Klasse ausf\u00fchren. Das Ergebnis wird im TestExplorer angezeigt.<\/p>\n<p>&nbsp;<\/p>\n<h1>Fluent Assertions<\/h1>\n<p>Die Bibliothek FluentAssertions erweitert das verwendete Testframework um einen Aspekt, der unsere Unit-Tests lesbarer macht. So liest sich die \u00dcberpr\u00fcfung unserer Behauptung wie wir sie oben formuliert haben ein wenig holprig:<\/p>\n<blockquote><p>\u201cBehaupte sind gleich, erwartet wie tats\u00e4chlich.\u201d<\/p><\/blockquote>\n<p>H\u00e4? Wer redet denn so einen Quatsch?<\/p>\n<p>W\u00e4re es nicht sch\u00f6ner, wenn wir unsere Behauptung in etwa so formulieren k\u00f6nnten:<\/p>\n<blockquote><p>\u201cTats\u00e4chliches Ergebnis sollte gleich sein mit erwartetem Ergebnis.\u201d<\/p><\/blockquote>\n<p>Das Klingt zugegebenerma\u00dfen immer noch ein wenig holprig. Versuchen wir das Ganze mal in Englisch:<\/p>\n<blockquote><p>\u201cActual should be expected.\u201d<\/p><\/blockquote>\n<p>In unseren Ohren klingt das doch ganz gut. FluentAssertions hilft uns dabei, unsere Behauptungen genau so zu formulieren.<\/p>\n<p>&nbsp;<\/p>\n<h2>Beispiele:<\/h2>\n<p>Schauen wir uns dasselbe Beispiel wie oben an, n\u00e4mlich dass 1 x 1 = 1 ist (sein sollte).<\/p>\n<pre class=\"lang:default decode:true\">[TestMethod]\r\npublic void OneTimesOneIsOne()\r\n{\r\n    IMultiplikation sut = new RussischeBauernmultiplikation();\r\n    sut.Mul(1, 1).Should().Be(1);\r\n}<\/pre>\n<p>Hier ist die Lesbarkeit schon h\u00f6her als oben beschrieben. Richtig spannend wird FluentAssertions in der Arbeit bestimmten Typen. Nachfolgend ein paar Ideen dazu:<\/p>\n<ul>\n<li>Strings\n<ul>\n<li>BeNull \/ NotBeNull<\/li>\n<li>BeEmpty \/ NotBeEmpty<\/li>\n<li>HaveLength<\/li>\n<li>StartWith \/ Contain \/ EndWith<\/li>\n<\/ul>\n<\/li>\n<li>Numerische Typen\n<ul>\n<li>Be \/ NotBe<\/li>\n<li>BeGreaterOrEqualTo<\/li>\n<li>BeLessThan<\/li>\n<li>BeInRange<\/li>\n<\/ul>\n<\/li>\n<li>Collections\n<ul>\n<li>NoBeEmpty<\/li>\n<li>HaveCount<\/li>\n<li>StartWith \/ EndWith<\/li>\n<li>BeSubsetOf<\/li>\n<li>Contain \/ OnlyContain<\/li>\n<\/ul>\n<\/li>\n<li>Datum\n<ul>\n<li>BeAfter \/ BeBefore<\/li>\n<li>HaveDay \/ HaveMonth \/ HaveYear<\/li>\n<\/ul>\n<\/li>\n<li>Ausnahmen\n<ul>\n<li>ShouldThrow<\/li>\n<li>WithMessage<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p>Dar\u00fcber hinaus k\u00f6nnen\u00a0 Behauptungen auch kombiniert werden. Grunds\u00e4tzlich sollte immer nur ein Konzept innerhalb eines Tests gepr\u00fcft werden, aber FluentAssertions bietet auch die M\u00f6glichkeit Behauptungen zu verkn\u00fcpfen (<em>AND<\/em> \/ <em>OR<\/em>).<\/p>\n<pre class=\"lang:c# decode:true \">[TestMethod]\r\npublic void StringWithFluentAssertions()\r\n{\r\n    string testString = \"Dies ist ein Text\";\r\n    testString.Should().Be(\"Dies ist ein Text\");\r\n    testString.Should().NotBe(\"Dies ist kein Text\");\r\n    testString.Should().BeEquivalentTo(\"DIES ist EIN Text\");\r\n\r\n    testString.Should().Contain(\"t e\");\r\n    testString.Should().NotContain(\"ist kein\");\r\n\r\n    testString.Should().StartWith(\"Dies\");\r\n    testString.Should().NotStartWith(\"Das\");\r\n    testString.Should().StartWithEquivalent(\"dies\");\r\n\r\n    testString.Should().EndWith(\"ein Text\");\r\n\r\n    testString.Should().Be(\"Dies ist ein Text\").And.Contain(\"t e\");\r\n}<\/pre>\n<p>&nbsp;<\/p>\n<h1>moq<\/h1>\n<p>W\u00e4hrend wir mit den vorgenannten Werkzeuge grunds\u00e4tzlich Unit-Tests schreiben k\u00f6nnen, hilft uns moq dabei unsere Tests von ggf. vorhandenen externen Einfl\u00fcssen zu isolieren. Falls euch jetzt nicht klar sein sollte, was wir damit meinen, lest noch einmal den Artikel <a href=\"http:\/\/invidit.de\/blog\/von-tests-und-komponenten\/\">Von Tests und Komponenten<\/a>. Hier wird auf die Notwendigkeit und die unterschiedlichen M\u00f6glichkeiten eingegangen.<\/p>\n<h2>Beispiele:<\/h2>\n<p>moq ist ein sehr m\u00e4chtiges Werkzeug. In diesem Rahmen m\u00f6chten wir euch die wichtigsten Anwendungsf\u00e4lle zur Isolation erl\u00e4utern, das Stubbing.<\/p>\n<p>Wir rufen eine Methode auf und k\u00f6nnen mit Hilfe von moq festlegen, welchen Wert diese Methode zur\u00fcckgeben soll. Der folgende Test wird erfolgreich durchlaufen:<\/p>\n<pre class=\"lang:c# decode:true \">[TestMethod]\r\npublic void testMockitoSimpleWhenThenReturn()\r\n{\r\n    var mock = new Mock&lt;IMultiplikation&gt;();\r\n    mock.Setup(imp =&gt; imp.Mul(1, 3)).Returns(5);\r\n\r\n    mock.Object.Mul(1, 3).Should().Be(5);\r\n}<\/pre>\n<p>Die Methode <em>Mul(1, 3) <\/em>unserer Implementierung gibt den Wert 3 zur\u00fcck (1\u00d73 = 3). Wir haben moq auf Basis des Interfaces aber folgendes gesagt:<\/p>\n<blockquote><p>\u201cWenn die Methode Mul mit den Parametern 1 und 3 aufgerufen wird, gebe den Wert 5 zur\u00fcck.\u201d<\/p><\/blockquote>\n<p>Damit wir das \u00fcberhaupt tun k\u00f6nnen, m\u00fcssen wir zun\u00e4chst mit Hilfe von moq einen <em>mock<\/em> der Klasse erstellen, dessen Methodenr\u00fcckgabe wir ver\u00e4ndern m\u00f6chten. In unserem obigen Fall handelt es sich dabei um ein Interface, es kann aber auch eine Klasse sein.<\/p>\n<p>Wichtig zu wissen ist, dass bei einem Mock immer nur die Methoden einen Wert zur\u00fcckgeben, die wir auch konfiguriert haben. Erg\u00e4nzen wir noch folgenden Assert, wird der Test fehlschlagen:<\/p>\n<pre class=\"lang:c# decode:true \">mock.Object.Mul(1, 1).Should().Be(1);<\/pre>\n<blockquote><p>Test Name:\u00a0\u00a0 \u00a0testMockitoSimpleWhenThenReturn<br \/>\nTest FullName:\u00a0\u00a0 \u00a0TestExamples.MoqExamples.testMockitoSimpleWhenThenReturn<br \/>\nTest Outcome:\u00a0\u00a0 \u00a0Failed<br \/>\nTest Duration:\u00a0\u00a0 \u00a00:00:00,1369741<\/p>\n<p>Result Message:\u00a0\u00a0 \u00a0Expected 1, but found 0.<\/p><\/blockquote>\n<p>Die Methode <em>Mul<\/em> haben wir nur f\u00fcr die Parameter (1, 3) konfiguriert. Rufen wir sie mit (1, 1) auf, wird der Initialwert des R\u00fcckgabetyps (in unserem Fall <em>int<\/em>) zur\u00fcckgegeben (dieser ist bei <em>int<\/em> 0).<\/p>\n<p>Neben dem beschriebenen Stubbing wird beim Mocking <strong>nicht<\/strong> das eigentliche Testobjekt gepr\u00fcft, sondern ob die Aufrufe auf dem Mock-Objekt wie erwartet erfolgt sind.<\/p>\n<pre class=\"lang:c# decode:true \">[TestMethod]\r\npublic void testNextIsCalled()\r\n{\r\n    var randMock = new Mock&lt;Random&gt;();      \r\n    Dice sut = new Dice(2, randMock.Object);\r\n    sut.Roll();\r\n\r\n    randMock.Verify(imp =&gt; imp.Next());\r\n}<\/pre>\n<p>Damit wird in unserem Beispiel die Methode <em>Roll()<\/em> indirekt gepr\u00fcft. Dies kann dann sinnvoll sein, wenn gepr\u00fcft wird, ob der Aufruf einer Abh\u00e4ngigkeit mit korrekten Parametern erfolgt.<\/p>\n<p>&nbsp;<\/p>\n<h2>Matcher<\/h2>\n<p>M\u00f6chten wir Methodenaufrufe mit beliebigen Parametern konfigurieren, m\u00fcssen wir sog. <em>Matcher<\/em> verwenden:<\/p>\n<pre class=\"lang:c# decode:true \">[TestMethod]\r\npublic void testMockitoSimpleWhenThenReturn()\r\n{\r\n    var mock = new Mock&lt;IMultiplikation&gt;();\r\n    mock.Setup(imp =&gt; imp.Mul(It.IsAny&lt;int&gt;(), 3)).Returns(5);\r\n\r\n    mock.Object.Mul(1, 3).Should().Be(5);\r\n    mock.Object.Mul(2, 3).Should().Be(5);            \r\n}<\/pre>\n<p>Die Klasse <em>Moq.It<\/em> stellt verschiedene Matcher zur Verf\u00fcgung, welche zur Konfiguration von Stubs verwendet werden k\u00f6nnen.<\/p>\n<h2><\/h2>\n<h2>Ein \u201cechtes\u201d Beispiel<\/h2>\n<p>Die oben aufgef\u00fchrten Beispiele sind nat\u00fcrlich nicht sinnvoll, sie dienen nur dem Zweck, die Funktionsweise von moq leicht verst\u00e4ndlich zu beschreiben. Hilfreich ist ein Mock immer dann, wenn wir unsere Klasse von Abh\u00e4ngigkeiten trennen wollen.<\/p>\n<p>Nehmen wir als Beispiel den Test der Klasse \u201cW\u00fcrfel\u201d, dessen Methode \u201cw\u00fcrfeln\u201d einen zuf\u00e4lligen Wert verwendet:<\/p>\n<pre class=\"lang:c# decode:true  \">public class Dice\r\n{\r\n    private int noOfDices;\r\n    private Random random;\r\n\r\n    public Dice(int noOfDices, Random random)\r\n    {\r\n        this.noOfDices = noOfDices;\r\n        this.random = random;\r\n    }\r\n\r\n    public int Roll()\r\n    {\r\n        int sum = 0;\r\n        for (int i = 0; i &lt; noOfDices; i++)\r\n        {\r\n            sum += random.Next();\r\n        }\r\n        return sum;\r\n    }\r\n}<\/pre>\n<p>Im Grunde ist die Methode nicht testbar, da hier immer andere Ergebnisse herauskommen, wenn von der Klasse <em>Random<\/em> die Methode <em>Next() <\/em>aufgerufen wird. Mit Hilfe von moq k\u00f6nnen wir die Methode aber trotzdem testen:<\/p>\n<pre class=\"lang:c# decode:true\">[TestMethod]\r\npublic void testRollWithTwoDicesReturnsCorrectSum() {\r\n    var randMock = new Mock&lt;Random&gt;();\r\n    randMock.Setup(imp =&gt; imp.Next()).Returns(4);\r\n    Dice sut = new Dice(2, randMock.Object);\r\n\r\n    sut.Roll().Should().Be(8);\r\n}<\/pre>\n<p>Dieser Test funktioniert. In dem wir festlegen, dass beim Aufruf von <em>Next()<\/em> immer ein fester Wert zur\u00fcckkommt, k\u00f6nnen wir testen, ob die Methode <em>Roll()<\/em> die Summe der Einzelw\u00fcrfe korrekt addiert.<\/p>\n<p>&nbsp;<\/p>\n<h1>Unsere Erfahrung mit\u00a0den Werkzeugen<\/h1>\n<p>Wir setzen insbesondere Microsoft Unit Testing Framework und Fluent Assertions ein, wenn wir unsere .Net-Projekte entwickeln. Fr\u00fcher haben wir NUnit verwendet, da Microsoft Unit Testing Framework in den Express-Editionen des Visual Studios nicht zur Verf\u00fcgung stand. Da Fluent Assertion beide Frameworks unterst\u00fctzt und Microsoft Unit Testing Framework mittlerweile immer &#8222;an Bord&#8220; ist, verwenden wir dies aus reiner Bequemlichkeit. Sie leisten uns gute Dienste und unterst\u00fctzen dabei, den Code abzusichern. Mit moq haben wir erst sehr wenig Erfahrung gesammelt und faktisch bislang in keinem Projekt eingesetzt. Wir haben unsere Mocks bislang immer manuell erstellt. Das werden wir aber in Zukunft sicher \u00e4ndern, da es ein gro\u00dfartiges Werkzeug ist.<\/p>\n<p>&nbsp;<\/p>\n<h1>Zusammenfassung<\/h1>\n<p>Mit Hilfe der hier vorgestellten Werkzeuge und Beispiele solltet ihr in der Lage sein, euren Code elegant und automatisiert testen zu k\u00f6nnen. NUnit und Microsoft Unit Testing Framework bilden die Basis aller Unit-Tests. Fluent Assertions erweitert &#8211; die bereits sehr elegante Schreibweise von NUnit seit Version 2.4 (Constraint-Based Assert Model) &#8211; und Microsoft Unit Testing Framework um n\u00fctzliche Funktionen und sinnvolle, einfach lesbare Syntax. moq hilft dabei, Tests von der umliegenden Infrastruktur zu trennen und auch Legacy-Code testbar zu machen ohne gleich die gesamte Code-Basis auf den Kopf stellen zu m\u00fcssen.<\/p>\n<p>Wir hoffen, dass es euch hiernach leichter f\u00e4llt, euren sauberen Code auch funktional abzusichern.<\/p>\n<p>Viel Spa\u00df beim Anwenden.<\/p>\n<p>Eure Spa\u00df-Coder<\/p>\n<p>&nbsp;<\/p>\n<p>Weitere Infos zu den Bibliotheken:<\/p>\n<ul>\n<li>NUnit &#8211; <a href=\"http:\/\/www.nunit.org\/\">http:\/\/www.nunit.org\/<\/a><\/li>\n<li>NUnit Plugin f\u00fcr Visual Studio &#8211; <a href=\"http:\/\/www.nunit.org\/index.php?p=vsTestAdapter&amp;r=2.6.2\">http:\/\/www.nunit.org\/index.php?p=vsTestAdapter&amp;r=2.6.2<\/a><\/li>\n<li>Microsoft Unit Testing Framework &#8211; <a href=\"https:\/\/msdn.microsoft.com\/en-us\/library\/ms243147.aspx\">https:\/\/msdn.microsoft.com\/en-us\/library\/ms243147.aspx<\/a><\/li>\n<li>FluentAssertions &#8211; <a href=\"http:\/\/www.fluentassertions.com\/\">http:\/\/www.fluentassertions.com\/<\/a><\/li>\n<li>moq &#8211; <a href=\"https:\/\/github.com\/Moq\/moq4#moq\">https:\/\/github.com\/Moq\/moq4#moq<\/a><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>Hallo Spa\u00df Coder, in den letzten Artikeln Testautomatisierung, Von Tests und Komponenten sowie Kein Unit-Test wie jeder andere haben wir euch hei\u00df darauf gemacht, euren Code automatisiert auf funktionale Richtigkeit hin zu \u00fcberpr\u00fcfen. In diesem Artikel m\u00f6chten wir euch ein paar Werkzeuge vorstellen, mit dessen Hilfe ihr euren .Net-Code automatisiert testen k\u00f6nnt. Wir setzen dabei [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":457,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[90],"tags":[29,87,69,77,75,85,84],"_links":{"self":[{"href":"https:\/\/invidit.de\/blog\/wp-json\/wp\/v2\/posts\/459"}],"collection":[{"href":"https:\/\/invidit.de\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/invidit.de\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/invidit.de\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/invidit.de\/blog\/wp-json\/wp\/v2\/comments?post=459"}],"version-history":[{"count":27,"href":"https:\/\/invidit.de\/blog\/wp-json\/wp\/v2\/posts\/459\/revisions"}],"predecessor-version":[{"id":504,"href":"https:\/\/invidit.de\/blog\/wp-json\/wp\/v2\/posts\/459\/revisions\/504"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/invidit.de\/blog\/wp-json\/wp\/v2\/media\/457"}],"wp:attachment":[{"href":"https:\/\/invidit.de\/blog\/wp-json\/wp\/v2\/media?parent=459"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/invidit.de\/blog\/wp-json\/wp\/v2\/categories?post=459"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/invidit.de\/blog\/wp-json\/wp\/v2\/tags?post=459"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}