Ich habe Probleme mit unseren Unit-Tests, die wir in meinem Team implementieren. Wir versuchen, Komponententests in Legacy-Code einzufügen, der nicht gut entworfen wurde, und obwohl wir keine Schwierigkeiten mit der tatsächlichen Hinzufügung der Tests hatten, beginnen wir damit zu kämpfen, wie sich die Tests entwickeln.
Als Beispiel für das Problem nehmen wir an, Sie haben eine Methode, die im Rahmen ihrer Ausführung 5 andere Methoden aufruft. Ein Test für diese Methode kann darin bestehen, zu bestätigen, dass ein Verhalten auftritt, wenn eine dieser fünf anderen Methoden aufgerufen wird. Da ein Komponententest aus einem Grund und nur aus einem Grund fehlschlagen sollte, möchten Sie potenzielle Probleme beseitigen, die durch Aufrufen dieser anderen 4 Methoden verursacht werden, und sie verspotten. Groß! Der Komponententest wird ausgeführt, die gespielten Methoden werden ignoriert (und ihr Verhalten kann im Rahmen anderer Komponententests bestätigt werden), und die Überprüfung funktioniert.
Es gibt jedoch ein neues Problem: Der Komponententest hat genaue Kenntnisse darüber, wie Sie dieses Verhalten bestätigt haben und welche Änderungen an diesen anderen 4 Methoden in Zukunft vorgenommen wurden oder welche neuen Methoden zur übergeordneten Methode hinzugefügt werden müssen Dies führt dazu, dass der Gerätetest geändert werden muss, um mögliche Fehler zu vermeiden.
Natürlich könnte das Problem etwas gemildert werden, indem einfach mehr Methoden weniger Verhalten bewirken, aber ich hatte gehofft, dass es vielleicht eine elegantere Lösung gibt.
Hier ist ein Beispiel für einen Unit-Test, der das Problem erfasst.
Kurz gesagt, 'MergeTests' ist eine Unit-Test-Klasse, die von der von uns getesteten Klasse erbt und das Verhalten nach Bedarf überschreibt. Dies ist ein 'Muster', das wir in unseren Tests verwenden, um Aufrufe an externe Klassen / Abhängigkeiten zu überschreiben.
[TestMethod]
public void VerifyMergeStopsSpinner()
{
var mockViewModel = new Mock<MergeTests> { CallBase = true };
var mockMergeInfo = new MergeInfo(Mock.Of<IClaim>(), Mock.Of<IClaim>(), It.IsAny<bool>());
mockViewModel.Setup(m => m.ClaimView).Returns(Mock.Of<IClaimView>);
mockViewModel.Setup(
m =>
m.TryMergeClaims(It.IsAny<Func<bool>>(), It.IsAny<IClaim>(), It.IsAny<IClaim>(), It.IsAny<bool>(),
It.IsAny<bool>()));
mockViewModel.Setup(m => m.GetSourceClaimAndTargetClaimByMergeState(It.IsAny<MergeState>())).Returns(mockMergeInfo);
mockViewModel.Setup(m => m.SwitchToOverviewTab());
mockViewModel.Setup(m => m.IncrementSaveRequiredNotification());
mockViewModel.Setup(m => m.OnValidateAndSaveAll(It.IsAny<object>()));
mockViewModel.Setup(m => m.ProcessPendingActions(It.IsAny<string>()));
mockViewModel.Object.OnMerge(It.IsAny<MergeState>());
mockViewModel.Verify(mvm => mvm.StopSpinner(), Times.Once());
}
Wie ist der Rest von Ihnen damit umgegangen oder gibt es keine einfache Möglichkeit, damit umzugehen?
Update - Ich freue mich über jedes Feedback. Leider, und es ist keine Überraschung, scheint es keine großartige Lösung, Muster oder Übung zu geben, die man beim Testen von Einheiten befolgen kann, wenn der getestete Code schlecht ist. Ich habe die Antwort markiert, die diese einfache Wahrheit am besten erfasst.