Frage

Ich bin mit C# 3.0 und NUnit.Ich Frage mich, ob es eine standard-Methode zur Durchführung von unit-tests auf code, der ausgeführt wird, nachdem einige Zeit.Zum Beispiel habe ich eine einfache statische Klasse, die ich registrieren kann, Methoden, die aufgerufen werden n Millisekunden später.Ich brauche, um sicherzustellen, dass code in der delegate-Methoden aufgerufen wird.

Für Beispiel, die folgenden test wird immer passieren, denn es sind keine Behauptungen aufgestellt, bis nach der Methode beendet wurde.

[Test]
public void SampleTest()
{
    IntervalManager.SetTimeout(delegate{ 
        Assert.Equals(now.Millisecond + 100, DateTime.Now.Millisecond); 
    }, 100);
}

Ist es sogar möglich, unit-test-code, der nicht sofort ausgeführt?

Cheers,

Paul

War es hilfreich?

Lösung

Wie wäre es damit? Es bewirkt, dass der Test für einige erwartete maximale Zeit für den Rückruf zu blockieren, einen Fehler zu feuern und abgeschlossen sein, bevor die Rettung, die Berichterstattung.

public void Foo() {
    AutoResetEvent evt = new AutoResetEvent(false);
    Timer t = new Timer(state => {
        // Do work
        evt.Set();
    }, null, 100, Timeout.Infinite);
    if (evt.WaitOne(500)) {
        // method called and completed
    } else {
        // timed out waiting
    }
}

Andere Tipps

Was genau testen Sie? Testen Sie, dass Timer arbeiten? Oder, dass der Code richtig abbindet einen Timer, so dass nach Ablauf bis der Timer einen Rückruf ausführt? Ohne zu wissen, was der Code aussieht, gehe ich davon aus, dass, was Sie wirklich wollen, zu testen, diese ist. Meine Antwort wäre, dass (1) es wahrscheinlich mit statischen Methoden schwer sein wird, und (2) Sie werden wahrscheinlich brauchen Dependency Injection zu verwenden und die Mock-Timer zu injizieren, usw., das das resultierende Verfahren nicht wirklich laufen, aber Rekord über die Erwartungen, dass die richtigen Anrufe wurden von Ihrem Code.

Als Randnotiz. Wir versuchen in der Regel unsere langsam laufenden Tests mit einem NUnit Kategorie zu markieren und können wählen, diese Tests überspringen auf einige bauen.

Ja, tut es so wie in deinem Beispiel funktioniert nicht.

Vielmehr empfehle ich Ihnen, erstellen Sie eine test-Klasse, zu verwendet werden als die Delegierten, dass Datensätze, wenn dessen Methode aufgerufen wurde und zu welcher Zeit.

Dann injizieren Sie Ihr mock in der IntervalManager Sie testen möchten.Ihre test-Methode muss dann warten, bis die IntervalManager (unter Verwendung einer geeigneten Methode zur Verfügung gestellt durch die IntervalManager, oder warten Sie einfach ein paar Sekunden), dann können Sie überprüfen Sie den Status des Tests.Klasse.

BTW, dieser Ansatz ist in der Regel bezeichnet als mocking;in diesem Fall wird der test-Klasse wäre das mock-Objekt.

Wie ein paar andere Antworten angegeben haben, sind langlaufende Tests im Allgemeinen eine schlechte Idee. Um dies zu erleichtern Komponente zu testen, sollten Sie bedenken, dass Sie wirklich zwei verschiedene Dinge, die Sie versuchen, zu testen.

  1. Wenn Sie eine zeitlich delegieren Ausführung die richtige Zeit registrieren gesetzt. Dies muss wahrscheinlich mit verschiedenen Kombinationen von Timeouts und Anzahl der Teilnehmer getestet werden.
  2. Der Delegierte in der richtigen Art und Weise ausgeführt werden.

die Tests in der Art und Weise trennen Sie erlauben würde, zu überprüfen, ob Ihr Timing-Mechanismus wie erwartet mit einer geringen Anzahl von kurzen Timeouts arbeitet (Testen aller Fälle, die Sie beachten müssen). Denken Sie daran, dass Sie wahrscheinlich ein wenig Spielraum in der tatsächlichen Zeit benötigen, dass es einen bestimmten Delegierten auszuführen nimmt auf der Grundlage der aktuellen Belastung des Systems und wie komplex Ihre Komponentencode ist (dh in IntervalManager).

Natürlich können Sie es testen. Sie müssen nur warten, bis es auszuführen.

Vielleicht etwas bin ich dabei, aber Visual Studio Unit-Tests haben spezielle Eigenschaften, die Sie auf Methoden setzen können Ausführungsreihenfolge und andere Dinge zu steuern. Dies sollte automatisch generiert wurden, wenn Sie zuerst die Unit-Tests Projekt vorgenommen:

    #region Additional test attributes
    // 
    //You can use the following additional attributes as you write your tests:
    //
    //Use ClassInitialize to run code before running the first test in the class
    //[ClassInitialize]
    //public static void MyClassInitialize(TestContext testContext) {
    //}
    //
    //Use ClassCleanup to run code after all tests in a class have run
    //[ClassCleanup()]
    //public static void MyClassCleanup()
    //{
    //}
    //
    //Use TestInitialize to run code before running each test
    //[TestInitialize()]
    //public void MyTestInitialize()
    //{
    //}
    //
    //Use TestCleanup to run code after each test has run
    //[TestCleanup()]
    //public void MyTestCleanup()
    //{
    //}
    //
    #endregion

So verwenden [ClassInitialize] sollten Sie erlauben zu schreiben, was zuerst in eine Methode auszuführen hat. Dann können Sie Ihre Tests laufen. Oder Sie können [TestInitialize] Code auszuführen vor jedem Test.

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