Frage

Bär mit mir, ich bin neu in NUnit. Ich komme aus dem Land der Schienen, so dass einige diese ist mir neu.

Ich habe eine Codezeile, die wie folgt aussieht:

var code = WebSiteConfiguration.Instance.getCodeByCodeNameAndType("CATALOG_Brands_MinQty", item.Catalog);

Ich versuche, es zu verspotten, wie dies (unter der Annahme code bereits initialisiert):

var _websiteConfigurationMock = new DynamicMock(typeof(WebSiteConfiguration));
_websiteConfigurationMock.ExpectAndReturn("getCodeByCodeNameAndType", code);

Wenn ich den Test debuggen, getCodeByCodeNameAndType kehrt null, statt der erwarteten code. Was mache ich falsch?

NUnit Version: 2.2.8

War es hilfreich?

Lösung

Ein DynamicMock erstellt ein neues Objekt im Speicher, der die Schnittstelle darstellt, oder rangierbaren (erbt von MarshalByRef) Klasse, die Sie wollen verspotten.

Versuchen Sie folgendes:

var _websiteConfigurationMock = new DynamicMock(typeof(WebSiteConfiguration));
_websiteConfigurationMock.ExpectAndReturn("getCodeByCodeNameAndType", code);
WebSiteConfiguration conf = (WebSiteConfiguration)_websiteConfigurationMock.MockInstance;
var x = conf.getCodeByCodeNameAndType("CATALOG_Brands_MinQty", item.Catalog);
Hinweis

, dass die dritte Linie wird es nicht funktionieren, wenn WebSiteConfiguration von MarshalByRef erbt.

Was Sie in der Regel tun, ist eine Schnittstelle Mock und ein neues Objekt erhalten, die diese Schnittstelle implementiert, sondern verhält sich so, wie Sie es tun konfiguriert haben, ohne dafür eine konkrete Art zu gehen und machen, so bin ich nicht ganz sicher, was Sie tun, wenn Sie eine bessere Isolation Framework verwenden, um Arbeit zu gehen, wie TypeMock, die Anrufe zu den statischen Methoden / Eigenschaften in bestehende Objekte abfangen kann.

Andere Tipps

Es tut mir leid, aber ich habe NUnit.Mocks nie benutzt - aber ich habe einige Erfahrung mit NMock und Moq haben [die, nebenbei bemerkt, ich sehr empfehlen]. Normalerweise verwenden Sie eine spöttische Bibliothek Proxies für Schnittstellendefinitionen zu erzeugen, und ich nehme an NUnit.Mocks die gleiche Art und Weise arbeitet.

Wenn Sie also Ihre Singleton verspotten mögen, werden Sie wahrscheinlich haben folgende zu tun,

a. Erstellen Sie eine Schnittstelle, sagen

// All methods you would like to mock from this class, should 
// be members of this interface
public interface IWebSiteConfiguration
{
    // Should match signature of method you are mocking
    CodeType getCodeByCodeNameAndType (
        string codeString, 
        CatalogType catalogType);
}

b. "Implementieren" Schnittstelle

// You've already written the method, interface matches signature,
// should be as easy as slapping interface on class declaration
public class WebSiteConfiguration : IWebSiteConfiguration { }

c. Verbrauchen Schnittstelle

in Ordnung, so Schritt c. die meisten Ihrer Arbeit ist, wo sein wird. Logisch, wenn Sie Ihre Singleton spotten, sind Sie tatsächlich Einheit der Verbraucher zu testen [, die Sie aus Ihrer Probe verlassen haben]. Für c. fügen Sie einfach einen Parameter in den Ctor des Verbrauchers oder fügen Sie eine öffentlich zugängliche Eigenschaft Typ ‚IWebSiteConfiguration‘ und intern Bezugs die Instanz Mitglied und rufen Sie Ihre Methoden gegen diese neue Schnittstelle dann. Betrachten Sie diese,

war

public class MyClass
{
    public MyClass () { }

    public void DoSomething ()
    {
        // bad singleton! bad boy! static references are bad! you
        // can't change them! convenient but bad!
        code = WebSiteConfiguration.Instance.getCodeByCodeNameAndType (
            "some.string", 
            someCatalog)
    }
}

wird

public class MyClass
{
    private readonly IWebSiteConfiguration _config = null;

    // just so you don't break any other code, you can default
    // to your static singleton on a default ctor
    public MyClass () : this (WebSiteConfiguration.Instance) { }

    // new constructor permits you to swap in any implementation
    // including your mock!
    public MyClass (IWebSiteConfiguration config) 
    {
        _config = config;
    }

    public void DoSomething ()
    {
        // huzzah!
        code = _config.getCodeByCodeNameAndType ("some.string", someCatalog)
    }
}

In Ihrem Gerät zu testen, die Mock erstellen, einen Verweis des Mock an die Verbraucher weitergeben, und die Verbraucher testen.

[Test]
public void Test ()
{
    IWebSiteConfiguration mockConfig = null;
    // setup mock instance and expectation via
    // NUnit.Mocks, NMock, or Moq

    MyClass myClass = new MyClass (mockConfig);
    myClass.DoSomething ();

    // verify results
}

Dies dient auch als praktische Einführung in Dependency Injection [DI]. Es ist einfach die Praxis der Weitergabe oder „Einspritzen“, Referenzen der Dienste [zB Konfigurationsklasse Website] für den Verbraucher, anstatt die Verbraucher den Dienst direkt [zB über statische Singletonklasse] aufrufen.

Hope, das hilft:)

Es scheint, gibt es eine Art von Lösung für diese mithilfe von Reflektion, oder vielleicht das ich total falsch verstanden.

Es wird hier diskutiert: http: //www.geekbeing .com / 2010/05/23 / how-to-Unit-Test-Singleton-Hack-in-c

Könnte es wirklich funktioniert?

public class TestableSingleton : SingletonClass
{
  public TestableSingleton ()
  {
    FieldInfo fieldInfo = typeof(SingletonClass)
        .GetField("_instance",
        BindingFlags.Static | BindingFlags.NonPublic);
    fieldInfo.SetValue(Instance, this);
  }
}

Projekt verfügbare auf https://github.com/rbabreu/TestableSingleton

Eigentlich konnte ich nicht kompilieren es auf Visual Studio, da die SingletonClass einen privaten Konstruktor haben würde. Wenn jemand es wäre toll, an der Arbeit den Aufwand für das Adaptermuster zu vermeiden.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top