c# - setupsequence - Wie kann ich Mock-Objekte in meinen Komponententests verwenden und trotzdem Code Coverage verwenden?




moq verify (3)

Das macht sehr viel Sinn. Im Wesentlichen sagst du, dass ich Folgendes tun muss:

public class MyClass
{
    public virtual string GetSomeString(MyOtherClass moc)
    {
        return moc.ToString();
    }
}

.....

Mock<MyOtherClass> myMock = new Mock<MyOtherClass>();

MyClass mc = new MyClass();

string someString = mc.GetSomeString(myMock.Object);
Assert.AreEqual(EXPECTED_STRING, someString);

Das SUT im Wesentlichen instantiieren und nur Mocks für die Klassen verwenden, die das SUT erfordert?

Momentan fange ich an, das Konzept der Mock-Objekte in meine Unit Tests einzuführen. Insbesondere verwende ich das Moq-Framework. Eines der Dinge, die ich bemerkt habe, ist jedoch, dass die Klassen, die ich mit diesem Framework teste, plötzlich eine Codeabdeckung von 0% zeigen.

Jetzt verstehe ich, dass, da ich nur die Klasse verspotte, es nicht die eigentliche Klasse selbst läuft .... aber wie schreibe ich diese Tests und habe Code Coverage genaue Ergebnisse zurückgeben? Muss ich eine Reihe von Tests schreiben, die Mocks und einen Satz verwenden, um die Klasse direkt zu instanziieren.

Vielleicht mache ich etwas falsch, ohne es zu merken?

Hier ist ein Beispiel, wie ich versuche, eine Klasse namens "MyClass" zu testen:

using Moq;
using NUnitFramework;

namespace MyNameSpace
{
    [TestFixture]
    public class MyClassTests
    {

        [Test]
        public void TestGetSomeString()
        {
            const string EXPECTED_STRING = "Some String!";

            Mock<MyClass> myMock = new Mock<MyClass>();
            myMock.Expect(m => m.GetSomeString()).Returns(EXPECTED_STRING);

            string someString = myMock.Object.GetSomeString();

            Assert.AreEqual(EXPECTED_STRING, someString);
            myMock.VerifyAll();

        }

    }

    public class MyClass
    {
        public virtual string GetSomeString()
        {
            return "Hello World!";
        }
    }
}

Weiß jemand, was ich anders machen sollte?


Ich würde empfehlen, sich von spöttischen Frameworks fern zu halten, bis Sie die Interaktionen verstehen, die hier ablaufen.

IMO ist es besser, mit manuell erstellten Testdoppelungen zu lernen, und dann zu einem spöttischen Rahmen zu gelangen. Meine Argumentation:

  1. Verspottende Frameworks abstrahieren, was tatsächlich passiert; Es ist einfacher, die Interaktionen zu erfassen, wenn Sie Ihre Abhängigkeiten explizit erstellen müssen, und dann den Tests im Debugger folgen.

  2. Es ist einfach, Frameworks zu missbrauchen. Wenn Sie beim Lernen selbst rollen, können Sie die Unterschiede zwischen verschiedenen Arten von Testdoppelungen besser verstehen. Wenn Sie direkt zu einem spöttischen Rahmen gehen, ist es einfach, Mocks zu verwenden, wenn Sie Stubs wollten und umgekehrt - es gibt einen großen Unterschied.

Stellen Sie sich das so vor: Die Klasse im Test steht im Mittelpunkt. Sie erstellen eine Instanz davon, rufen ihre Methoden auf und bestätigen dann, dass das Ergebnis korrekt ist. Wenn die zu testende Klasse Abhängigkeiten aufweist (z. B. ist etwas im Konstruktor erforderlich), erfüllen Sie diese Abhängigkeiten, indem Sie entweder A: echte Klassen oder B: Test doubles verwenden.

Der Grund, warum wir Testdoppelungen verwenden, besteht darin, dass sie die zu testende Klasse isoliert, was bedeutet, dass Sie ihren Code in einer kontrollierteren Art und Weise ausüben können.

Wenn Sie z. B. eine Klasse mit einem Netzwerkobjekt haben, können Sie die Fehlerbehandlungsroutinen der besitzenden Klasse, die tote Verbindungen erkennen, nicht testen, wenn Sie gezwungen sind, ein konkretes Netzwerkverbindungsobjekt zu verwenden. Stattdessen injizieren Sie ein gefälschtes Verbindungsobjekt und weisen es an, eine Ausnahme auszulösen, wenn die Methode "SendBytes" aufgerufen wird.

Dh In jedem Test werden die Abhängigkeiten der zu testenden Klasse spezifisch erzeugt, um einen bestimmten Codeabschnitt auszuüben.


Sie verwenden Ihre Mock-Objekte nicht korrekt. Wenn Sie Mock-Objekte verwenden, sollten Sie testen, wie Ihr Code mit anderen Objekten interagiert, ohne die realen Objekte zu verwenden. Siehe den folgenden Code:

using Moq;
using NUnitFramework;

namespace MyNameSpace
    {
        [TestFixture]
        public class MyClassTests
        {

            [Test]
            public void TestGetSomeString()
            {
                const string EXPECTED_STRING = "Some String!";

                Mock<IDependance> myMock = new Mock<IDependance>();
                myMock.Expect(m => m.GiveMeAString()).Returns("Hello World");

                MyClass myobject = new MyClass();

                string someString = myobject.GetSomeString(myMock.Object);

                Assert.AreEqual(EXPECTED_STRING, someString);
                myMock.VerifyAll();

            }

        }

        public class MyClass
        {

            public virtual string GetSomeString(IDependance objectThatITalkTo)
            {
                return objectThatITalkTo.GiveMeAString();
            }
        }

        public interface IDependance
        {
            string GiveMeAString();
        }
    }

Es sieht nicht so aus, als würde es etwas Nützliches tun, wenn der Code nur eine Zeichenkette ohne Logik zurückgibt.

Die tatsächliche Leistung kommt, wenn Sie GetSomeString() Methode GetSomeString() eine Logik erstellt haben, die das Ergebnis der Ausgabezeichenfolge in Abhängigkeit von der Rückgabe des IDependdance . GiveMeAString() -Methode, dann können Sie sehen, wie Ihre Methode fehlerhafte Daten behandelt, die von der IDependdance Schnittstelle IDependdance werden.

Etwas wie:

 public virtual string GetSomeString(IDependance objectThatITalkTo {
     if (objectThatITalkTo.GiveMeAString() == "Hello World")
     return "Hi";
 }

Wenn Sie diese Zeile in Ihrem Test haben:

myMock.Expect(m => m.GiveMeAString()).Returns(null);

Was passiert mit Ihrer GetSomeString() -Methode?







code-coverage