Autofixture: Erstellen Sie eine alternative GuardClauseAssertion, die Methoden unterstützt, die mit "async" gekennzeichnet sind.

Erstellt am 1. März 2019  ·  12Kommentare  ·  Quelle: AutoFixture/AutoFixture

Wie in #268 besprochen, wartet die Klasse GuardClauseAssertion nicht auf den Abschluss der Aufgaben, wodurch sie nicht in der Lage ist, fehlerfreie schnelle Methoden zu validieren.

Dies ist völlig verständlich, da das schnelle Durchfallen in der Tat die beste Option ist. Nichtsdestotrotz scheint es unmöglich, Fail-Fast- Verhalten zu implementieren async .

enhancement

Hilfreichster Kommentar

@ploeh Grundsätzlich ist die Methode _any_ async nicht fehlerfrei. Betrachten Sie das folgende Beispiel:

```c#
öffentliche asynchrone AufgabeBewachtOpenGenericMethodReturningTaskResult(Objektargument)
{
if (arg == null) throw new ArgumentNullException(nameof(arg));

await Task.Yield();

return default;

}
```

Diese Methode löst nicht aus, wenn Sie sie null aufrufen. Stattdessen wird das fehlgeschlagene Task zurückgegeben. Daher versagt die GuardClauseAssertion in ihrer jetzigen Form und beschwert sich über fehlende GuardClause.

In einer echten Anwendung ist fast der gesamte Code async , daher ist jeder Aufruf awaited und eine Ausnahme wird sofort ausgelöst. Es ist also völlig in Ordnung, dass das "Fast-Fail"-Prinzip in einer Form verletzt wird, die Sie await Task ausführen sollten, um eine Ausnahme zu sehen.

Natürlich können Sie Code irgendwie neu schreiben, damit er sofort fehlschlägt (erstellen Sie eine private Funktion mit dem Schlüsselwort async und verschieben Sie die gesamte Logik dorthin), aber es hat keinen praktischen Sinn, dies zu tun.

Alle 12 Kommentare

es scheint unmöglich, das Verhalten _fail fast_ zu implementieren, wenn Methoden verwendet werden, die mit dem Schlüsselwort async .

Wie so? Können Sie ein Beispiel geben?

@ploeh Grundsätzlich ist die Methode _any_ async nicht fehlerfrei. Betrachten Sie das folgende Beispiel:

```c#
öffentliche asynchrone AufgabeBewachtOpenGenericMethodReturningTaskResult(Objektargument)
{
if (arg == null) throw new ArgumentNullException(nameof(arg));

await Task.Yield();

return default;

}
```

Diese Methode löst nicht aus, wenn Sie sie null aufrufen. Stattdessen wird das fehlgeschlagene Task zurückgegeben. Daher versagt die GuardClauseAssertion in ihrer jetzigen Form und beschwert sich über fehlende GuardClause.

In einer echten Anwendung ist fast der gesamte Code async , daher ist jeder Aufruf awaited und eine Ausnahme wird sofort ausgelöst. Es ist also völlig in Ordnung, dass das "Fast-Fail"-Prinzip in einer Form verletzt wird, die Sie await Task ausführen sollten, um eine Ausnahme zu sehen.

Natürlich können Sie Code irgendwie neu schreiben, damit er sofort fehlschlägt (erstellen Sie eine private Funktion mit dem Schlüsselwort async und verschieben Sie die gesamte Logik dorthin), aber es hat keinen praktischen Sinn, dies zu tun.

In einer echten Anwendung ist fast der gesamte Code async , daher ist jeder Aufruf awaited und eine Ausnahme wird sofort ausgelöst.

Das ist ein fairer Punkt; Ich akzeptiere dieses Argument.

Ich werde manchmal abgelenkt, wenn jemand behauptet oder (mit wenig Beweisen) impliziert, dass etwas _unmöglich_ ist...

Ich werde manchmal abgelenkt, wenn jemand behauptet oder (mit wenig Beweisen) impliziert, dass etwas unmöglich ist ...

Ja, es ist fair genug 😉

Lassen Sie mich nun versuchen, darüber nachzudenken, wie ich GuardClauseAssertion umgestalten kann, um keine booleschen Flags zu haben - ich mag es auch nicht, um fair zu sein. Bis später in PR.

Lassen Sie mich nun versuchen, darüber nachzudenken, wie ich GuardClauseAssertion umgestalten kann, um keine booleschen Flags zu haben

Ich würde denken, dass, wie @moodmosaic vorgeschlagen hat, eine neue Klasse ein besseres Design sein könnte. Ich habe mich jedoch nicht intensiv mit dem Problem befasst, also behalte ich mir das Recht vor, mich zu irren 😄

Hier ist die Lösung, die ich verwendet habe.

  1. Entfernen Sie das Schlüsselwort async der Methodensignatur
  2. Erstellen Sie eine verschachtelte Methode mit dem Schlüsselwort async
  3. Setzen Sie die Schutzklauseln in den äußeren Teil der Methode
  4. Rufen Sie die verschachtelte Methode auf und geben Sie die Ergebnisse zurück

Beispiel:

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

Für mich war es eine gute Lösung. Danke für Ihre Hilfe.

@mniak Interessant, ein konkretes Beispiel dafür zu haben, was @zvirja hier vorgeschlagen

Ich persönlich mag es nicht wirklich, weil wir die Methode mit "Tricks" zu Gunsten des Testing-Frameworks verschmutzen, was für mich wirklich schlecht riecht und ich nicht möchte, dass mein Team dieses Muster verwendet.

Halten Sie es offen, um den Support auf native Weise zu implementieren. Ein Tag. In naher Zukunft. Oder nur einen Tag.

Hi. Wir sind über genau dieses Problem gestolpert und waren überrascht, dass es bisher keine gute Lösung gibt.
Gibt es Gründe dafür keine neue Klasse zu implementieren?
Ich kenne die inneren Details von AutoFixture nicht, aber wenn wir eine MethodInfo in der Klasse GuardClauseAssertion für die Method-to-Test verfügbar hätten, können wir uns ihre CustomAttributes ansehen und feststellen, ob es sich um eine Async-Methode handelt oder nicht (https:/ /stackoverflow.com/a/20350646). Ein Schalter (bool vs. new class) ist also vielleicht nicht einmal notwendig.

@zvirja @aivascu könnten wir das noch einmal überdenken? Ich verstehe wirklich nicht, warum im Jahr 2021 asynchrone Methoden nicht richtig getestet werden können.

@Kralizek Wenn ich die Situation richtig gelesen habe, wurde die Anfrage nicht abgelehnt und es gibt sogar eine PR, die das behebt.
Ich habe mir die PR kurz angeschaut und muss sagen, dass ich dem Feedback, das sie erhalten hat, zustimme.
Es bleibt also nur noch, entweder das Feedback umzusetzen oder eine neue PR mit dem implementierten Feedback einzureichen.

Ich konnte die verlinkte PR in der mobilen App nicht sehen 😅

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen

Verwandte Themen

malylemire1 picture malylemire1  ·  7Kommentare

JoshKeegan picture JoshKeegan  ·  6Kommentare

Accc99 picture Accc99  ·  4Kommentare

zvirja picture zvirja  ·  8Kommentare

Ridermansb picture Ridermansb  ·  4Kommentare