Autofixture: Trate os delegados como falsos com FakeItEasy

Criado em 16 fev. 2018  ·  15Comentários  ·  Fonte: AutoFixture/AutoFixture

Até onde eu sei, o AutoFixture trata automaticamente interfaces e tipos abstratos como mockables. Acho que é uma boa ideia incluir os tipos de delegados nesta lista também.

enhancement good first issue

Comentários muito úteis

Lançado em v4.2.0! Para habilitar:
c# fixture.Customize(new AutoFakeItEasyCustomization { GenerateDelegates = true });

Todos 15 comentários

Em primeiro lugar, você poderia esclarecer com qual framework de mocking você trabalha? Temos algumas integrações (Moq, NSubsitute, FakeItEasy), então não está claro. Pelo que eu sei, os delegados já são suportados pela integração do Moq (pelo menos isso é mencionado em # 742).

Até onde eu sei, o AutoFixture tem seu próprio mecanismo de geração de delegados. Você tem algum problema com isso?

@zvirja Eu uso o FakeItEasy. Então, estou mudando o título do problema
O código a seguir retorna um Fake após a personalização aplicada:
var myFake= fixture.Create<ISomeInterface>();

No entanto, o seguinte não:
var myFake= fixture.Create<Func<int,int>>();

O código acima apenas retorna um delegado fictício não falso.

Além disso, o seguinte trava com um erro:

var myFake= fixture.Create<Fake<Func<int,int>>>();

AutoFixture.ObjectCreationExceptionWithPath
HResult = 0x80131500
Message = AutoFixture não conseguiu criar uma instância de System.IntPtr porque a criação falhou inesperadamente com exceção. Consulte a exceção interna para investigar a causa raiz da falha.

Caminho do pedido:
FakeItEasy.Fake 1[System.Func 2 [System.Int32, System.Int32]]
Método IntPtr
System.IntPtr

Mensagens de exceção interna:
AutoFixture.Kernel.IllegalRequestException: Uma solicitação de IntPtr foi detectada. Este é um recurso inseguro que travará o processo se usado, portanto, a solicitação é negada. Uma fonte comum de solicitações IntPtr são solicitações de delegados, como Funcou ação. Se for esse o caso, a solução alternativa esperada é Personalizar (Registrar ou Injetar) o tipo ofensivo especificando uma estratégia de criação adequada.

Fonte =
StackTrace:

Exceção interna 1:
IllegalRequestException: uma solicitação de IntPtr foi detectada. Este é um recurso inseguro que travará o processo se usado, então a solicitação é negada. Uma fonte comum de solicitações IntPtr são solicitações de delegados, como Funcou ação. Se for esse o caso, a solução alternativa esperada é Personalizar (Registrar ou Injetar) o tipo ofensivo especificando uma estratégia de criação adequada.

@OnurGumus Investiguei brevemente esse problema e não parece que FakeItEasy apóia a zombaria de delegados. Os delegados não são mencionados em sua documentação.

Além disso, testei o código a seguir e ele falhou com uma exceção (o que prova que esse recurso não é compatível):
c# A.Fake<Func<int, int>>();

Portanto, não parece que o AutoFixture possa fazer algo sobre isso também.

Você poderia descrever o comportamento desejado com mais detalhes? É muito fácil simular um delegado, já que ele pode ser especificado por meio de uma expressão lambda primitiva, então por que você precisa de simulações?

@zvirja , FakeItEasy certamente apóia Fakes para delegados:
image

@blairconrad Você poderia, por favor, encontrar alguns minutos e lançar alguma luz sobre isso? O FakeItEasy apóia a zombaria dos delegados? Em caso afirmativo, qual é a sintaxe? Minha amostra acima falhou para mim, mas pode acontecer que eu perdi algo ...: confused:

Obrigado: piscadela:

@zvirja , feliz em. Como @OnurGumus diz, o FakeItEasy fingirá felizmente os delegados (e criei um problema para documentar isso).
No entanto, AutoFakeItEasy nunca se preocupou em falsificar delegados.

Ao falsificar um Fake<Func<int, int>> , por exemplo, FakeItEasyMethodQuery.SelectMethods falha porque não considera o caso Fake<T> onde T é um delegado. A mudança muito ingênua abaixo corrige isso.

@@ -33,7 +33,7 @@ namespace Ploeh.AutoFixture.AutoFakeItEasy
             }

             var fakeType = type.GetFakedType();
-            if (fakeType.IsInterface)
+            if (fakeType.IsInterface || fakeType.IsSubclassOf(typeof(Delegate)))
             {
                 return new[] { new ConstructorMethod(type.GetDefaultConstructor()) };
             }

Então posso criar e usar um Fake<Func<int, int>> .

Quanto à criação de um Func<int, int> , experimentei rapidamente e descobri que o aparelho usava DelegateGenerator para criar um delegado (não FakeItEasy).
Entre você e eu, sempre me confundi com a arquitetura do AutoFixture e a relação entre um construtor e um relé e outros enfeites, mas posso continuar a explorar e ver onde está a lacuna.

Estou de volta. Eu posso entender. O FakeItEasyRelay é adicionado aos coletores de resíduos do aparelho, mas o DelegateGenerator cria um delegado primeiro.
Uma pesquisa rápida não revelou como inserir o construtor FakeItEasy no início da cadeia, mas posso não estar procurando.

Independentemente de como isso aconteça, ficaria feliz em enviar um PR para permitir a zombaria de Fake<TDelegate> onde TDelegate é um tipo de delegado.

@blairconrad como usuário FakeItEasy, anseio por sua RP :)

@blairconrad Obrigado pelos esclarecimentos e pela sua investigação! Acabei de verificar mais uma vez e descobri que o FakeItEasy realmente cria as falsificações para os delegados. Provavelmente, perdi algo no meu teste anterior 😖

Quanto à criação de um Func, Experimentei rapidamente e descobri que o acessório usava DelegateGenerator para criar um delegado (não FakeItEasy).

Sim. Temos exatamente o mesmo problema com o Moq - o AutoFixture intercepta essas solicitações antes que ResidueCollectors tenha a oportunidade de intervir.

Sugiro corrigir esse problema da seguinte maneira:

  • Estenda a consulta de método para oferecer suporte a solicitações de Fake<Delegate> ;
  • Adicione uma nova personalização, que adicionará retransmissão à coleção Customizations , de forma que a solicitação de delegação seja tratada (retransmitida) _antes_ de ser processada pelo kernel do AutoFixture. Ou seja, esse recurso não será ativado por padrão, no entanto, os usuários podem ativá-lo facilmente usando uma personalização predefinida.

@blairconrad Além disso, você poderia descrever qual é a vantagem do delegado falso em relação ao criado pela AutoFixtura? Por enquanto, apenas uma coisa me vem à mente - você pode configurá-los usando a sintaxe de configuração de biblioteca falsa.

Obrigado, @zvirja.

Eu acho que você está certo. O benefício de um delegado falso seria que ele poderia ser configurado usando a sintaxe de configuração de biblioteca falsa.

Estou feliz em estender a consulta de método para oferecer suporte a Fake<Delegate> , e irei adicionar uma personalização adicional, como você disse, mas pergunto: aquele que oferece suporte a Delegate bom o suficiente? O que acontece quando o próximo bug relatado deseja que IEnumerable ou Task ou IDictionary tenham sido falsificados por FakeItEasy?

Oh, @zvirja pediu confirmação sobre a sintaxe para falsificar um delegado. Agora ele foi incorporado à documentação do FakeItEasy com o FakeItEasy / FakeItEasy # 1321, mas para ser explícito:

`` `c #
var fakeDelegate = A.Fake> ();

is the preferred syntax for clients, although "unnatural fakes" can be used:

```c#
var fakeDelegate = new Fake<Func<int, int>>();

O último é como a classe FakeItEasyBuilder criaria o Fake.

Curiosidade: os delegados falsos não eram suportados até a versão 1.7.4257.42 (provavelmente cometa FakeItEasy / FakeItEasy @ edb4f61d0db0a84b68c7a9395f2661a58579d34a). Pessoalmente, não tenho nenhum problema em dizer "você não entende isso a menos que use pelo menos essa versão do FakeItEasy". @zvirja ou outros, você considera isso um problema? Terei que fazer alguns truques com os testes de unidade para ter certeza de não quebrar os testes AutoFakeItEasyUnitTest existentes.
A menos que você queira atualizar a versão mínima do FakeItEasy para esta correção. Eu provavelmente não faria isso, especialmente porque solicitar um delegado teria falhado nessas versões de qualquer maneira.

@blairconrad Muito obrigado pelo seu trabalho nisso!

@zvirja ou outros, você considera isso um problema?

Não de todo. De acordo com o SemVer que estamos seguindo aqui, não temos permissão para alterar a versão de dependência dentro da mesma versão principal. Portanto, eu diria que a etapa certa seria adicionar esse suporte para as versões FakeItEasy que suportam o recurso. Posteriormente, podemos querer descartar o suporte 1.x na v5 (para consistência), mas isso acontecerá apenas no futuro.

Converter esse problema em um recurso, conforme concordamos em prosseguir (e o FakeItEasy oferece suporte aos delegados).

Lançado em v4.2.0! Para habilitar:
c# fixture.Customize(new AutoFakeItEasyCustomization { GenerateDelegates = true });

Esta página foi útil?
0 / 5 - 0 avaliações

Questões relacionadas

ploeh picture ploeh  ·  7Comentários

DeafLight picture DeafLight  ·  5Comentários

gtbuchanan picture gtbuchanan  ·  3Comentários

Accc99 picture Accc99  ·  4Comentários

Ephasme picture Ephasme  ·  3Comentários