2015-10-15 15 views
6

Ich habe einen Job, in dem ich einen IDisposable DbContext habe. Ich würde gerne diesen Job testen, ohne in eine Datenbank zu gehen. Welche Möglichkeiten muss ich haben?Wie wird mit einem IDisposable-Repository mit Unity verfahren?

Ich benutze die Standard-Fakes-Assembly 'von Microsoft.

Mein Beruf:

public void Work() 
{ 
    do 
    { 
     //code here     
     using (var repository = new Repository<User>()) 
     { 
      repository.Save(user); 
     } 

    } while (true); 
} 

Ich versuche, zu testen und in diesem Teil des Tests versagt, weil es tatsächlich eine neue Instanz der Repository-Klasse erstellt.

Mein Test-Methode:

using (ShimsContext.Create()) 
{ 
    Data.Repository.Fakes.ShimRepository<Domain.Fakes.ShimUser>.Constructor = (a) => { }; 

    Data.Repository.Fakes.ShimRepository<Domain.Fakes.ShimUser>.AllInstances.SaveT0 = (a, b) => 
    { 
    }; 

    var service = GetService(); 
    service.Work(); //Throws exception 
} 

Wie kann ich gefälschte diese Save Methode?

+1

siehe Dependency Injection - Sie müssen einen übergebenen Parameter an Work() übergeben. Oder zumindest in den Dienst, ansonsten erstellt er immer einen echten. –

+0

Ich kenne mich mit Fakes nicht aus, aber vielleicht ist es nicht voll genug für Ihre Bedürfnisse. Ich weiß, das ist trivial mit einer Bibliothek wie Moq (https://github.com/Moq/moq4). –

+0

Es wäre auch nicht trivial mit Moq, da er eine tatsächliche konkrete Instanz des Repository in der Arbeit instanziiert. –

Antwort

7

Sie haben DIP hier verletzt, wodurch das Testen von Geräten wesentlich schwieriger wird, als es sein sollte. Sie sollten auch generische Repositories vermeiden und role interfaces bevorzugen.

Stattdessen injizieren Sie eine Abstraktion in Ihren Dienst Ihres Repository, z. IUsersRepository definiert Ihre Save Methode. Dann können Sie in Ihrem Komponententest des Dienstes einfach eine Stub-Implementierung von IUsersRepository verwenden.

+0

Ja, aber wie wäre es mit der Entsorgung des Objekts? Wenn ich es einmal einschicke, läuft der Job für immer mit der ersten Instanz des Kontextes. – gog

+0

Disposing ist ein Implementierungsdetail der Entity Framework-Implementierung der Abstraktion. Daher wird die Entsorgung z. EntityFrameworkUsersRepository. – devdigital

2

Fakes neigen zu zeigen, dass der Code nicht richtig, die D in SOLID folgenden, da Sie in ihnen Abhängigkeiten innerhalb Ihrer Klasse statt vorbei schaffen.

Eine viel bessere Muster würde eine ISaveRepository Schnittstelle zu schaffen, die wiederum implementiert IDisposable mit einer offengelegten Methode Save(). Sie sollten dann eine Instanz Ihres Repositorys in Ihre Klasse einfügen. Auf diese Weise können Sie die Verwendung von Anweisungstests erfüllen und einen Mock implementieren, der eine .Save()-Methode definiert, die nicht auf die Datenbank trifft.

+0

Wie wäre Dispose für viele Implementierungen nicht erforderlich? – gog

+0

Wird Ihre Stub-Implementierung benötigt werden? Wird ein XML-Repository benötigt? Wird ein Web-Service-Aufruf-Repository benötigt? usw. usw. – devdigital

+0

@ggui Ich gehe davon aus, dass Sie ursprünglich die Verbindung neu erstellten, um zu vermeiden, eine Verbindung für einen längeren Zeitraum zu halten? –

Verwandte Themen