Comme discuté dans #268, la classe GuardClauseAssertion
n'attend pas la fin des tâches, ce qui la rend incapable de valider les méthodes rapides sans
C'est tout à fait compréhensible, puisque le fail fast est en effet la meilleure option. Néanmoins, il semble impossible d'implémenter un comportement d' async
.
il semble impossible d'implémenter le comportement _fail fast_ lorsqu'il s'agit de méthodes marquées avec le mot-clé
async
.
Comment? Pouvez vous donner un exemple?
@ploeh Fondamentalement, la méthode _any_ async
n'est pas rapide. Considérez l'exemple suivant :
```c#
Tâche publique asynchrone
{
if (arg == null) throw new ArgumentNullException(nameof(arg));
await Task.Yield();
return default;
}
```
Cette méthode ne lance pas si vous l'appelez null
. Au lieu de cela, le Task
échoué est renvoyé. Par conséquent, la GuardClauseAssertion dans sa forme actuelle échoue et se plaint d'une clause de garde manquante.
Dans une application réelle, presque tout le code est async
, donc chaque invocation est awaited
et l'exception est levée immédiatement. Il est donc tout à fait normal que le principe "fast-fail" soit violé sous une forme que vous devriez await
Task pour voir l'exception.
Bien sûr, vous pouvez réécrire le code d'une manière ou d'une autre pour le faire échouer immédiatement (créer une fonction privée avec le mot-clé async
et y déplacer toute la logique), mais cela n'a aucun sens pratique.
Dans une application réelle, presque tout le code est
async
, donc chaque invocation estawaited
et l'exception est levée immédiatement.
C'est un bon point; J'accepte cet argument.
Je suis parfois distrait lorsque quelqu'un affirme ou laisse entendre (avec peu de preuves) que quelque chose est _impossible_...
Je suis parfois distrait quand quelqu'un affirme ou laisse entendre (avec peu de preuves) que quelque chose est impossible...
Ouais, c'est assez juste
Maintenant, laissez-moi essayer de réfléchir à la façon dont je peux reconcevoir GuardClauseAssertion
pour ne pas avoir de drapeau booléen - je ne l'aime pas non plus, pour être juste. A plus tard dans PR.
Maintenant, laissez-moi essayer de réfléchir à la façon dont je peux reconcevoir
GuardClauseAssertion
pour ne pas avoir de drapeau booléen
Je pense que, comme @moodmosaic l'a suggéré, une nouvelle classe pourrait être un meilleur design. Je n'ai pas étudié la question de près, donc je me réserve le droit de me tromper
Voici la solution que j'ai utilisé.
async
de la signature de la méthodeasync
Exemple:
public Task<int> GetNumberAsync(MyObject obj)
{
// Fail-fast behavior
if (request is null)
throw new ArgumentNullException(nameof(obj));
async Task<int> work()
{
var items = await obj.GetItemsAsync(); // whatever you need to call
return items.Count();
}
return work();
}
Cela a été une bonne solution pour moi. Merci de votre aide.
@mniak Intéressant d'avoir un exemple concret de ce que @zvirja a suggéré ici .
Personnellement je n'aime pas trop ça car on pollue la méthode avec des "trucs" au profit du framework de test, ce qui me sent vraiment mauvais et je ne voudrais pas que mon équipe utilise ce modèle.
Gardez-le ouvert pour implémenter le support de manière native. Un jour. Dans un futur proche. Ou juste un jour.
Salut. Nous avons trébuché exactement sur ce problème et avons été surpris qu'il n'existe pas de bonne solution jusqu'à présent.
Y a-t-il des raisons de ne pas implémenter une nouvelle classe pour cela ?
Je ne connais pas les détails internes d'AutoFixture, mais si nous avions un MethodInfo disponible dans la classe GuardClauseAssertion pour la méthode à tester, nous pouvons jeter un œil à ses CustomAttributes et identifier s'il s'agit d'une méthode Async ou non (https :/ /stackoverflow.com/a/20350646). Donc, peut-être qu'un changement (bool contre nouvelle classe) n'est même pas nécessaire.
@zvirja @aivascu pourrait-on reconsidérer cela ? Je ne vois vraiment pas pourquoi en 2021, les méthodes asynchrones ne peuvent pas être testées correctement.
@Kralizek si j'ai bien lu la situation, la demande n'a pas été rejetée, et il y a même un PR qui la corrige.
J'ai jeté un bref coup d'œil au PR et je dois dire que je suis d'accord avec les commentaires qu'il a reçus.
Il ne reste donc plus qu'à mettre en œuvre les commentaires ou à déposer un nouveau PR avec les commentaires mis en œuvre.
Je ne pouvais pas voir le PR lié dans l'application mobile 😅
Commentaire le plus utile
@ploeh Fondamentalement, la méthode _any_
async
n'est pas rapide. Considérez l'exemple suivant :```c#GardéOuvertGénériqueMéthodeRetourTâcheRésultat(objet argument)
Tâche publique asynchrone
{
if (arg == null) throw new ArgumentNullException(nameof(arg));
}
```
Cette méthode ne lance pas si vous l'appelez
null
. Au lieu de cela, leTask
échoué est renvoyé. Par conséquent, la GuardClauseAssertion dans sa forme actuelle échoue et se plaint d'une clause de garde manquante.Dans une application réelle, presque tout le code est
async
, donc chaque invocation estawaited
et l'exception est levée immédiatement. Il est donc tout à fait normal que le principe "fast-fail" soit violé sous une forme que vous devriezawait
Task pour voir l'exception.Bien sûr, vous pouvez réécrire le code d'une manière ou d'une autre pour le faire échouer immédiatement (créer une fonction privée avec le mot-clé
async
et y déplacer toute la logique), mais cela n'a aucun sens pratique.