2010-12-19 9 views
0

Meine Anwendung hat die folgende Projektstruktur: Es gibt das Business-Logik-Projekt und das UnitTesting-Projekt, wo die Methoden aus der Business-Logik getestet werden. Es wird kein Mocking oder Testing Framework verwendet (wir setzen auf Visual Studio Unit Tests und implementieren unsere eigenen Mock-Objekte). In der Business-Logik lassen Sie uns sagen, dass ich die folgende Methode haben: dassMock-Objekt für Komponententests eher mehr zu OOP Frage

public static void SomeMethod() 
{ 
    .... 
    if (cond1) 
     if (cond2) 
      SendMail(); 
} 

ich Unit-Test soll. Ich möchte nicht das Senden der E-Mail testen, sondern die E-Mail wird unter den richtigen Umständen gesendet. So war ich so etwas wie

public class MailSender : ISmtpMail 
{ 
    // stuff 
} 

public class FakeMailSender : ISmtpMail 
{ 
    // 
    static bool SendMail() 
    { 
     return true; 
    } 
} 

Das Problem zu tun, das Denken ist, dass ich weiß nicht, wie die Nutzung der FakeMailSender in dem Unit-Test-Projekt oder in der Einheit Testmethoden, die wie etwas aussehen zu erzwingen:

[TestMethod] 
public static void SomeMethod_Test() 
{ 
    // some mock initialization 
    BusinessLogic.SomeMEthod(); 
    // checks 
} 

ohne die Businesslogic Methode Signatur zu ändern oder Injizieren Code (was unerwünscht ist)

+0

Es wäre gut, wenn Sie erklären, warum injizierender Code unerwünscht ist, da dies eine ausgezeichnete Möglichkeit ist, Ihr Problem zu lösen. –

Antwort

2

Es ist nicht klar, wo Ihre erste Methode "lebt". Es scheint mir, dass:

  • Ihre SendMail Methode nicht statisch sein sollte, die alle Arten von Testdoppeleinspritzung heikel die am wenigsten
  • Sie sollten ISmtpMail injizieren in dem, was E-Mail senden muss sagen macht.

Sie sagen, Sie möchten es tun "ohne Code zu injizieren" - warum nicht? Der Dienst "E-Mail-Versand" ist eindeutig eine Abhängigkeit: Ihr Code wird klarer, weniger eng gekoppelt und einfacher zu testen, wenn Sie diese Abhängigkeit explizit oder mit Hilfe eines DI-Containers injizieren.

1

Das Problem ist, dass Sie static Methoden verwenden. Es gibt keine saubere Möglichkeit, diese Singleton-Instanz so zu konfigurieren, dass sie verschiedene Dienste verwendet.

Betrachten Sie dies. Machen Sie Ihre SomeMethod nicht-statische und injizieren die erforderlichen Dienste in die Geschäftslogik Beispiel:

private ISmtpMail _smtpMail; 
public BusinessLogic(ISmtpMail smtpMail) 
{ 
    _smtpMail = smtpMail; 
} 

public void SomeMethod() 
{ 
    ... 
    _smtpMail.Send(); 
} 

Ihre Test-Code wird dann in der Lage sein zu erzwingen, welcher Dienst zu verwenden:

[TestMethod] 
public static void SomeMethod_Test() 
{ 
    // some mock initialization 
    var bl = new BusinessLogic(new FakeMailSender()); 
    bl.SomeMethod(); 
    // checks 
} 

Für Produktionscode Ich empfehle Ihnen dringend, einige der hervorragenden Dependency-Injection-Frameworks, z Autofac, wodurch die Service-Injektionen mehr oder weniger durch Magie geschehen.

1

Mit Statik können Sie kommerzielle Bibliothek wie Typemock verwenden. Wenn Sie jedoch gezwungen sind, das zu verwenden, bedeutet das, dass Sie ein schlechtes Design haben, wahrscheinlich sogar das Konzept von oop missverstehen. Ich würde empfehlen, die Injektion umzuformulieren und zu verwenden, wie Jon Skeet und Peter Lillevold bereits vorgeschlagen haben.

0

Zuerst sollten Sie vermeiden, statische Spott zu verwenden, und verwenden Sie das klassische Injektionsmuster wie bereits vorgeschlagen.

Wenn Sie jedoch statische Methoden wirklich vortäuschen möchten (z. B. in Fällen, in denen Sie diesen Code nicht ändern können, weil sich dieser Code in der Drittanbieterbibliothek befindet), können Sie Moles verwenden.jedes Mal erzeugen kann Ihr Code ruft diese ursprüngliche Methode

namespace MyNamespace { 
    class MailSender 
    { 
     public static bool SendMail() {...} 
    } 
} 

Moles „Maulwurf“ für diese Klasse mit Aktionsdelegate Hexe statt ursprünglicher Methode genannt würde:

Angenommen, Sie folgende Mailsender Klasse haben. Und als Sie folgenden Test schreiben können:

[TestMethod] 
public static void SomeMethod_Test() 
{ 
    // After that all calls to MyNamespace.MailSender.SendMail whould 
    // return true 
    MyNamespace.Moles.MMailSender.SendMail =() => true; 
    BusinessLogicClass.SomeMethod(); 
} 

BTW, Moles kann Ihnen auch nicht nur statische Methoden spöttische helfen und nicht-virtuelle Methoden mit Mole, aber dieses Tool zum Testen Schnittstellen oder Klassen mit virtuellem ähnlichen Stub-Klassen erzeugen Methoden.