3 Stimmen

Integrationstests eines ViewModel, das asynchron WCF-Dienste aufruft in einer WPF MVVM-Anwendung

Das Silverlight Toolkit enthält Unit Testing-Funktionalitäten, die es ermöglichen, Klassen wie die ViewModels in einer MVVM-Anwendung zu testen, die Remote Services asynchron aufrufen.

Ich möchte in der Lage sein, meine ViewModel-Integrationstests gegen die tatsächlichen Dienste anstelle von gemockten Instanzen durchzuführen.

Gibt es Unterstützung für asynchrone Unit-/Integrationstests für WPF-Anwendungen?

Update:

Am Ende des Tages kombinierte meine Lösung die Vorschläge von ktutnik und Alex Paven. Ich schrieb eine kleine Hilfsklasse, die etwas syntaktischen Zucker hinzufügt:

public static class AsyncMethod
{
    public delegate void AsyncMethodCallback(AsyncMethodContext ctx);

    public static void Call(AsyncMethodCallback cb)
    {
        // erstelle das Synchronisationsobjekt und mache es über TLS verfügbar
        using (var syncObject = new AutoResetEvent(false))
        {
            // rufe die dekorierte Methode auf
            cb(new AsyncMethodContext(syncObject));
        }
    }
}

/// Asnc Method Callback Synchronization Context
public class AsyncMethodContext
{
    public AsyncMethodContext(EventWaitHandle syncObject)
    {
        this.syncObject = syncObject;
    }

    private readonly EventWaitHandle syncObject;

    /// 
    /// Wartet auf Abschluss.
    /// 
    public void WaitForCompletion()
    {
        syncObject.WaitOne();
    }

    /// 
    /// Signalisiert, dass der aktuelle Vorgang abgeschlossen ist
    /// 
    public void Complete()
    {
        syncObject.Set();
    }
}

Hier ist ein Beispiel-Testfall, kombiniert mit der Nutzung der Microsoft Rx Extensions:

[TestMethod]
public void TestGuestLogin()
{
    AsyncMethod.Call((ctx) =>
    {
        var vm = ServiceLocator.Get();

        // VM-Daten einrichten
        vm.Username = "guest";
        vm.Password = "guest";
        vm.AutoLogin = false;
        GenericInfoEventArgs loginResult = null;

        // Vorabprüfung
        Assert.IsTrue(vm.LoginCmd.CanExecute(null));

        // Observable für das LoginRequestComplete-Ereignis der VM erstellen
        var loginEvent = Observable.FromEvent>(vm, "LoginRequestComplete").Do((e) =>
        {
            Debug.WriteLine(e.ToString());
        });

        // sich dafür abonnieren
        var loginEventSubscription = loginEvent.Subscribe((e) =>
        {
            loginResult = e.EventArgs;

            // Test abgeschlossen
            ctx.Complete();
        });

        // Dinge in Bewegung setzen
        using (loginEventSubscription)
        {
            vm.LoginCmd.Execute(null);
            ctx.WaitForCompletion();

            Assert.IsTrue(loginResult.Info.Success, "Login war nicht erfolgreich");
        }
    });
}

3voto

ktutnik Punkte 5742

Ich habe lange nach diesem Feature gesucht, aber bisher kein Glück gehabt.

Nicht wirklich eine saubere Lösung, aber es funktioniert für mich. Ich benutze normalerweise ManualResetEvent, damit der Testprozess nicht abbricht, bis asynchron fertig ist. Hier ist die Idee:

//set false for initial state
resetEvent = new ManualResetEvent(false);
//do the test
myObjec.MakeMeHappyAssync();
//just wait until its state set 
//when your call done
resetEvent.WaitOne();
//do assertion here

Und irgendwo in Ihrer Complete-Methode oder Fault-Methode rufen Sie einfach

resetEvent.Set();

In jedem Fall, wenn Sie neue Informationen über das Feature finden, lassen Sie es mich bitte wissen.

Mit freundlichen Grüßen

1voto

Alex Paven Punkte 5507

Sie könnten sich die Reactive Extensions ansehen, die jetzt im .Net Framework 4 enthalten sind, vorausgesetzt, Sie verwenden es; es gibt auch Versionen für 3.5 und Silverlight. Sie ermöglichen eine angenehme asynchrone Kodierung, ich habe sie schon einmal beim Unit Testing verwendet. Siehe hier für einen Blog-Artikel dazu.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X