Betrachten Sie diese Klasse:
public class Content
{
public virtual bool IsCheckedOut {get; private set;}
public virtual void CheckOut()
{
IsCheckedOut = true;
}
public virtual void CheckIn()
{
//Do Nothing for now as demonstrating false positive test.
}
}
Die Checkin-Methode ist absichtlich leer. Nun habe ich ein paar Testmethoden, um den Status der einzelnen Methoden zu überprüfen.
[TestMethod]
public void CheckOutSetsCheckedOutStatusToTrue()
{
Content c = new Content();
c.CheckOut();
Assert.AreEqual(true, c.IsCheckedOut); //Test works as expected
}
[TestMethod]
public void CheckInSetsCheckedOutStatusToFalse()
{
Content c = new Content();
c.CheckIn();
Assert.AreEqual(false, c.IsCheckedOut); //Test does not work as expected
}
Der 2. Test besteht aus den falschen Gründen. Wie kann ich also mit Mocking (moq) überprüfen, ob das CheckIn die IsCheckedOut-Eigenschaft setzt?
Vielen Dank.
EDIT
Zur Klarstellung: Ich habe eine Methode namens CheckIn (), deren Aufgabe es ist, den IsCheckedOut-Status auf false zu setzen.
Sie sehen in meinem Testcode oben, dass der Test false zurückgibt, auch wenn ich den Eigenschaftswert nicht auf false setze. Dies wird erwartet, hier ist nichts falsch.
Ich denke, meine Frage ist spezifisch. Wie kann ich überprüfen, ob die CheckIn () - Methode die IsCheckedOut-Eigenschaft auf false festgelegt hat? Dies würde ich Verhaltensüberprüfung nennen.
Ich glaube, in einigen Kommentaren wurde vorgeschlagen, etwas zu tun, was einer Verifizierung des Staates gleichkommt. Wenn ja, glaube ich nicht, dass es einen Wert hat, diesen Teil überhaupt zu verspotten, wenn wir einfach Folgendes verwenden können:
Content c = new Content();
c.CheckIn();
Assert.AreEqual(false, c.IsCheckedOut); //State verification
Natürlich kann ich falsch liegen, also helfen Sie mir bitte, diese Konzepte zu klären :)
Folgendes sollte funktionieren. Konfigurieren Sie Ihr Mock-Objekt als:
var mock=new Mock<IContent>();
mock.SetupSet(content => content.IsCheckedOut=It.IsAny<bool>()).Verifiable();
Und nach dem Testcode:
mock.VerifySet(content => content.IsCheckedOut=It.IsAny<bool>());
Ich habe es sowieso nicht getestet, sagen Sie mir bitte, ob es für Sie funktioniert.
EDIT. In der Tat wird dies nicht funktionieren, da der Setzer für IsCheckedOut
falsch ist.
Wie auch immer, jetzt sehe ich, dass Sie niemals den Wert von IsCheckedOut
zur Klassenbauzeit setzen. Es ist eine gute Idee, der Content
-Klasse Folgendes hinzuzufügen:
public Content()
{
IsCheckedOut=false;
}
Mock mockContect = new Mock<Cotent>();
mockContent.VerifySet(x => x.IsCheckedOut, Times.Once());
Wird das den Trick tun? Nicht sicher, wie der private Setter kommt, weil er das nicht getestet hat. aber arbeitet für meinen öffentlichen Setzer.
Hab das von: http://www.codethinked.com/post/2009/03/10/Beginning-Mocking-With-Moq-3-Part-2.aspx
warum richten Sie den Inhalt nicht einfach so ein, dass er ausgecheckt werden kann? Denken Sie daran, dass Sie nur das Verhalten der CheckIn-Funktion testen.
[TestMethod]
public void CheckInSetsCheckedOutStatusToFalse()
{
// arrange - create a checked out item
Content c = new Content();
c.CheckOut();
// act - check it in
c.CheckIn();
// assert - IsCheckedOut should be set back to false
Assert.AreEqual(false, c.IsCheckedOut);
}
Darf ich vorschlagen, dass Sie falsch darüber nachdenken - im Allgemeinen sollten Sie etwas einrichten, eine Aktion ausführen und dann das Verhalten (Ergebnis) überprüfen. In diesem Fall spielt es wirklich eine Rolle, dass es vom Setter nicht auf "false" gesetzt wurde. Wichtig ist, dass es falsch ist, nachdem ein bestimmtes Szenario ausgeübt wurde. Wenn Sie Tests isoliert ablegen, mag dies etwas seltsam erscheinen, aber für alles, was Ihre Tests in Sets enthalten.
Die Situation wäre anders, wenn Sie die Interaktion zwischen zwei Klassen testen würden - dann wäre es gut, eine Erwartung für den Eigenschaftssetter festzulegen - da die Einstellungsaktion die Interaktion ist, die Sie testen.
Ich bin mit Moq nicht vertraut, da ich Rhino.Mocks verwende - aber ich schätze, es wird etwas in Richtung Mock.VerifySet geben (content => content.IsCheckedOut = It.IsEqual (true));
Ich stimme mit Ihnen überein: Spott hat in diesem Szenario keinen Wert, weil es beabsichtigt ist, die Wechselwirkungen zwischen Ihrer Klasse (im Test) und dem Rest der Welt zu testen, nicht den inneren Mechanismus Ihrer Klasse zu testen.
Ich denke das dieser Test
Content c = new Content();
c.CheckIn();
Assert.AreEqual(false, c.IsCheckedOut); //State verification
dass du schreibst, hat Sinn und ist nicht falsch positiv! Sie müssen sicherstellen, dass sich der Status nach dem Einchecken in dieser Weise befindet, unabhängig davon, warum es so ist. Wenn Sie in Zukunft den Status im Konstruktor (oder in anderen Methoden) festlegen, werden Sie durch diesen Test gerettet, und Sie müssen die CheckIn-Methode implementieren.
In einigen Fällen möchte ich den Anfangsstatus festlegen, um sicherzustellen, dass die CheckIn-Methode nicht vergessen wird. In diesem Fall verwende ich 2 Methoden (die erste ist sehr hässlich):
Hier ist der Code:
public class Content2
{
public virtual bool IsCheckedOut { get; protected set; }
public virtual void CheckOut()
{
IsCheckedOut = true;
}
public virtual void CheckIn()
{
//Do Nothing for now as demonstrating false positive test.
}
}
[TestClass]
public class Content2Test : Content2
{
[TestMethod]
public void CheckOutSetsCheckedOutStatusToTrue()
{
this.CheckOut();
Assert.AreEqual(true, this.IsCheckedOut); //Test works as expected
}
[TestMethod]
public void CheckInSetsCheckedOutStatusToFalse()
{
this.IsCheckedOut = true;
this.CheckIn();
Assert.AreEqual(false, this.IsCheckedOut); //Test does not work as expected
}
}
Hoffe zu helfen.