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");
}
});
}