Conforme discutido em # 268, a classe GuardClauseAssertion
não espera a conclusão das tarefas, tornando-a incapaz de validar métodos rápidos sem
Isso é completamente compreensível, uma vez que a falha rápida é de fato a melhor opção. No entanto, parece impossível implementar o comportamento de async
.
parece impossível implementar o comportamento _fail fast_ ao lidar com métodos marcados com a palavra-chave
async
.
Como assim? você pode dar um exemplo?
@ploeh Basicamente, o método _any_ async
não é rápido para falhas. Considere o seguinte exemplo:
`` `c #
tarefa assíncrona pública
{
if (arg == null) lança um novo ArgumentNullException (nameof (arg));
await Task.Yield();
return default;
}
`` `
Este método não joga se você chamá-lo de null
. Em vez disso, o Task
falha é retornado. Portanto, a GuardClauseAssertion em sua forma atual falha e reclama sobre a ausência da cláusula de proteção.
Na aplicação real, quase todo o código é async
, portanto, cada invocação é awaited
e a exceção é lançada imediatamente. Portanto, está tudo bem que o princípio de "falha rápida" seja violado de uma forma que você deve await
Tarefa para ver a exceção.
Claro, você pode reescrever o código de alguma forma para fazê-lo falhar imediatamente (criar função privada com a palavra-chave async
e mover toda a lógica para lá), mas não há nenhum sentido prático para fazer isso.
Na aplicação real, quase todo o código é
async
, portanto, cada invocação éawaited
e a exceção é lançada imediatamente.
Esse é um ponto justo; Eu aceito esse argumento.
Às vezes fico desviado quando alguém afirma ou insinua (com poucas evidências) que algo é _impossível _...
Às vezes fico desviado quando alguém afirma ou insinua (com poucas evidências) que algo é impossível ...
Sim, é justo 😉
Agora, deixe-me tentar pensar como posso redesenhar GuardClauseAssertion
para não ter uma bandeira booleana - eu também não gosto, para ser justo. Te vejo mais tarde no PR.
Agora, deixe-me tentar pensar como posso redesenhar
GuardClauseAssertion
para não ter uma bandeira booleana
Eu acho que, como sugeriu @moodmosaic , uma nova classe pode ser um design melhor. Eu não pesquisei muito sobre o problema, então me reservo o direito de estar errado 😄
Aqui está a solução que tenho usado.
async
da assinatura do métodoasync
Exemplo:
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();
}
Tem sido uma boa solução para mim. Obrigado pela ajuda.
@mniak Interessante ter um exemplo concreto do que @zvirja sugeriu aqui .
Pessoalmente, eu realmente não gosto disso porque estamos poluindo o método com "truques" para o benefício do framework de testes, que cheira muito mal para mim e eu não gostaria que minha equipe usasse esse padrão.
Mantenha-o aberto para implementar o suporte de maneira nativa. Um dia. Num futuro próximo. Ou apenas um dia.
Oi. Nós tropeçamos exatamente nesse problema e ficamos surpresos que nenhuma boa solução existe até agora.
Existem razões para não implementar uma nova classe para isso?
Não sei os detalhes internos do AutoFixture, mas se quisermos ter um MethodInfo disponível dentro da classe GuardClauseAssertion para o Method-to-Test, podemos dar uma olhada em seus CustomAttributes e identificar se é um método Async ou não (https: / /stackoverflow.com/a/20350646). Então, talvez, uma troca (bool vs. nova classe) nem seja necessária.
@zvirja @aivascu podemos reconsiderar isso? Eu realmente não vejo por que em 2021 os métodos assíncronos não podem ser testados corretamente.
@Kralizek se eu li a situação corretamente, o pedido não foi rejeitado e há até um PR que corrige isso.
Dei uma olhada rápida no PR e devo dizer que concordo com o feedback que ele recebeu.
Portanto, a única coisa que resta é implementar o feedback ou enviar um novo PR com o feedback implementado.
Não consegui ver o PR vinculado no aplicativo móvel 😅
Comentários muito úteis
@ploeh Basicamente, o método _any_
async
não é rápido para falhas. Considere o seguinte exemplo:`` `c #GuardedOpenGenericMethodReturningTaskResult(objeto arg)
tarefa assíncrona pública
{
if (arg == null) lança um novo ArgumentNullException (nameof (arg));
}
`` `
Este método não joga se você chamá-lo de
null
. Em vez disso, oTask
falha é retornado. Portanto, a GuardClauseAssertion em sua forma atual falha e reclama sobre a ausência da cláusula de proteção.Na aplicação real, quase todo o código é
async
, portanto, cada invocação éawaited
e a exceção é lançada imediatamente. Portanto, está tudo bem que o princípio de "falha rápida" seja violado de uma forma que você deveawait
Tarefa para ver a exceção.Claro, você pode reescrever o código de alguma forma para fazê-lo falhar imediatamente (criar função privada com a palavra-chave
async
e mover toda a lógica para lá), mas não há nenhum sentido prático para fazer isso.