C# How to unit-test einer interface-Methode ohne Implementierung
Ich bin neu in unit-Tests und stackoverflow.
Ich habe zum test RefreshAmount
in die folgende Schnittstelle:
public interface IAccountService
{
double GetAccountAmount(int accountId);
}
Und hier ist eine Klasse, die abhängig vom interface:
public class AccountObj
{
private readonly int _Id;
private readonly IService _service;
public AccountObj(int Id, IService service)
{
_Id = Id;
_service = service;
}
public double Amount { get; private set; }
public void RefreshAmount()
{
Amount = _service.GetAmount(_Id);
}
}
Wie kann ich die unit Tests das Verhalten der RefreshAmount
?
RefreshAmount
Anrufe IService.GetAmount
die können einen Anruf an einen back-end-office-muss ich aber nicht seine Umsetzung. Jede Anregung auf dem Weg zu gehen, würde geschätzt werden.
(Ich habe gelesen über moq und dependency injection, aber ich bin ruhig, neue unit-Test)
- Es fühlt sich ziemlich sinnlos zu testen, ein interface selbst, da es keine Implementierung zu testen. 1. Schreiben Sie eine Implementierung und testen mit unit-test-2. Wie Sie bereits erwähnt, können Sie mit Moq, um eine test-Implementierung des interfaces
- Ich glaube nicht, dass er testen will, die Schnittstelle aber wie
AccountObj
verwendet diese Schnittstelle. - Ihre
AccountObj
sieht aus wie eine Einheit. Sie sollten nicht injizieren von Abhängigkeiten in den Konstruktor Ihrer Entitäten.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Mit Moq, hier ist ein minimal-Beispiel test mit Kommentare
Und hier ist eine vereinfachte version des gleichen Tests
Ich nehme an, wenn Sie ein paar Tippfehler in deinem code, denn das interface aufgerufen wird
IAccountService
während Ihr Dienst implementiertIService
. Ihre Klasse wird aufgerufenAccountObj
während Ihr Konstruktor aufgerufen wirdAccountInfo
.Nehmen wir also an, Ihr Dienst wird erwartet, dass zur Umsetzung
IAccountService
und Ihre Klasse erwartet werden benanntAccountInfo
.Beim schreiben eines unit-test zu testen
AccountInfo.RefreshAmount
haben, müssen Sie sich bewusst sein, die Anforderungen dieser Funktion, müssen Sie genau wissen, was diese Funktion tun soll.Blick auf den code, es scheint, dass die Anforderungen der
RefreshAmount
ist:Oder formaler:
IAccountService
Weil die Bedingung sagt, es sollte Arbeit für alle Ids und alle AccountServices, Sie können nicht testen Sie Ihre Klasse mit allen von Ihnen. In solchen Fällen beim schreiben von unit-tests Sie denken müssen Fehler passieren.
In deinem Beispiel sieht es aus, dass es wahrscheinlich keine Fehler, aber für zukünftige Versionen könnte man denken, dass die Funktion würde den service rufen mit die falsche Id, oder rufen Sie den falschen Dienst, oder vergisst, zu speichern den Rückgabewert in Eigentum Betrag, oder, dass das Eigentum Betrag nicht wieder den korrekten Wert.
Den Anforderungen für die Klasse angeben, dass es funktionieren sollte für jede Id und jedes IAcocuntService. Dafür sind Sie frei, um alle Id-und AccountService an den Konstruktor des test-Objekt, das Sie testen möchten, werden wahrscheinlich erkennen, eine der vier zukünftigen Fehler.
Glücklicherweise eine Einfache AccountInfo-Klasse würden Ausreichen,
Folgende unit-test-tests, die die Menge ist die Menge zurück durch die bereitgestellte Implementierung von IAccountService für mehrere Ids
void TestAccountObj_RefreshAmount()
{
const int Id = 438;
IAccountService accountService = new AccountService();
var testObject = new AccountInfo(Id, accountService);
}
Dieser test prüft alle vier genannten wahrscheinlich Fehler. Der einzige Fehler, dass es nicht finden konnte ist, dass es nennen würde, der falsche Dienst, wenn dieses falsche service zurückgeben würde, genau das gleiche seltsame berechnete Zahl. Das ist der Grund, warum ich so eine komische Berechnung in den service, ist es sehr unwahrscheinlich, dass eine falsch genannte service-würde wieder den gleichen Fehler. Vor allem, wenn Sie möchten, testen Sie mit verschiedenen Testobjekt mit verschiedenen Ids
Unit Tests für solche Dinge ist in Bezug auf eine gute Zusammensetzung der Klasse. In diesem Fall ist. Sie können pass "service", um Ihre Klasse und das sollte die Arbeit für Sie erledigt.
Was Sie tun müssen ist, stellen Sie "testServiceClass" die Arbeit wird nur zum testen, aber nichts anderes.
HINWEIS: code unten fehlen alle "tests" - Attribute, um kurz den code
Ist es wichtig für Sie, dass die Klasse selbst aktiviert ist (UNIT-test), nicht die ganze Implementierung von verschiedenen Klassen über (INTEGRATIONS-test).
Ich weiß nicht, ist das Moq-frameworks. Wir verwenden MSTest und Microsoft Fakes, die Sie mit stubs.
Jedoch eine naive straight forward Weg sein könnte, um die Implementierung der Schnittstelle in einer test-Klasse
Und Ihr test Methode:
Wenn Sie nur wollen, um zu überprüfen, dass die daraus resultierenden
Amount
korrekt ist, lassen Sie die anderen Eigenschaften. Normalerweise wollen Sie nicht, um zu überprüfen wieRefreshAmount()
tut, was es tun sollte, aber nur, wenn die resultierendeAmount
korrekt ist.Ich empfehle, dass Sie verwenden Moq für das, was Sie versuchen zu erreichen. Es ermöglicht es Ihnen, "Gefälschte" eine Implementierung der Schnittstelle, die Sie auf der Durchreise sind die Klasse, die Sie versuchen zu testen. Auf diese Weise werden Sie nur das Verhalten einer Klasse zu einem Zeitpunkt. Dadurch wird die unit-Tests eine ganze Menge einfacher auf lange Sicht.
Erstellen einer test-Klasse scheint wie eine einfache option, aber, wenn Sie sich den Umgang mit einer großen Anzahl von Szenarien, die test-Klasse, um zu wachsen und komplizierter werden gerecht aller Szenarien, und irgendwann werden Sie haben, um zu testen, ob auch wegen seiner Komplexität.
Versuchen, zu lernen, wie moq, es wird sich auszahlen auf lange Sicht. Sie werden in der Lage sein, um Daten zu überprüfen übergeben, verspottet, Objekt, Steuerung, was zurückgegeben verspottet Verhalten, zu testen, ob verspottet Methoden aufgerufen wurden und wie oft Sie aufgerufen wurden. Moq ist extrem nützlich.
Haben Sie einen Blick auf https://github.com/Moq/moq4/wiki/Quickstart es wird erläutert, wie Moq ganz gut für Anfänger