5 votes

Comment puis-je tester que les implémentations sont synchrones ou asynchrones lorsqu'elles doivent l'être ?

J'essaie d'écrire des tests unitaires autour d'un programme personnalisé SynchronizationContext mise en œuvre.

Les deux opérations importantes sur cette classe sont Send y Post , donde Send invoque un délégué de manière synchrone et Post invoque un délégué de manière asynchrone.

J'aimerais écrire des tests unitaires pour vérifier ce comportement, à savoir que les délégués ont été exécutés de manière synchrone ou asynchrone. Je ne veux pas que les tests s'appuient sur des délais pour les cas de réussite, car cela prolonge artificiellement l'exécution des tests (mais il est raisonnable que les échecs provoquent un délai).

Au départ, j'ai envisagé d'utiliser des tâches pour signaler l'exécution d'un délégué :

var tcs = new TaskCompletionSource<object>();

var context = new CustomSynchronizationContext();

context.Send((state) => tcs.SetResult(null), null);

// Task should already be completed!
Assert.IsTrue(this.tcs.Task.IsCompleted);

Cependant, cela ne garantit pas que le délégué a été pas exécuté de manière asynchrone très rapidement avant que le coureur de test ne puisse continuer.

Comment puis-je organiser un test autour du contexte pour m'assurer que Send bloque l'achèvement du délégué et Post ne le fait pas, mais que les délégués son tous deux invoqués ?

3voto

Rich Points 164

Je pense que vous pouvez y parvenir en utilisant une paire de ManualResetEvents . En utilisant le code ci-dessous, le ralentissement n'est ressenti que si les tests ont échoué (les chiffres sont assez élevés et pourraient probablement être réduits sans danger). L'idée ici est que nous affirmons l'ordre dans lequel les choses doivent se produire qui ne peut se produire que si nous bloquons ou ne bloquons pas.

Pour le test synchrone :

var incall = new ManualResetEvent(false);
var unblock = new ManualResetEvent(false);
var context = new CustomSynchronizationContext();
var t = Task.Run(() => context.Send(state =>
{
    incall.Set();
    unblock.WaitOne(5000);
}, null));
Assert.IsTrue(incall.WaitOne(1000));
Assert.IsFalse(t.Wait(10));
unblock.Set();
Assert.IsTrue(t.Wait(1000));

pour le test Async :

var incall = new ManualResetEvent(false);
var unblock = new ManualResetEvent(false);
var context = new CustomSynchronizationContext();
var t = Task.Run(() =>context.Post(state =>
{
    incall.Set();
    unblock.WaitOne(5000);
}, null));
Assert.IsTrue(incall.WaitOne(1000));
Assert.IsTrue(t.Wait(1000)); //This will timeout if unblock is blocking completion of the task
unblock.Set();

-1voto

Davio Points 1906

Incorporer mon idée :

var mainThreadId = Thread.ManagedThreadId;
var sendThreadId;
context.Send((state) => sendThreadId = Thread.ManagedThreadId);
Assert.AreEqual(mainThreadId, sendThreadId);

Je ne sais pas si ça marche vraiment, vous devrez vérifier.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X