Oi,
Estou tentando obter a instância da Interface Mocked interna criada por AutoMoqData para configurar a interface.
Existe uma maneira de fazer algo assim
[Theory, AutoMoqData]
public void Dummy(IFixture fixture, ComplexClassWithInnerInterface sut)
{
fixture.GetInstance<IInnerInterfaceMockCreatedByAutoMoqData>().Setup(x => x.Method).Result(something);
Assert.Equal(String.Empty, String.Empty);
}
Obrigado
Experimente
Mock.Get(sut).Setup(x => x.Method).Result(something);
Você obterá a instância do objeto não criada pelo Moq. acessando sut.
Isso realmente funcionará se a interface for uma propriedade pública.
Mock.Get (sut.InnerInterface) .Setup (x => x.Method) .Result (algo);
Mas e se a interface for simulada e o construtor injetado, registrado no contêiner IoC, mas não acessível em sut com uma propriedade pública?
Neste caso, você terá que congelar a simulação para garantir que a instância gerada também será injetada no sut:
[Theory, AutoMoqData]
public void Dummy(
IFixture fixture,
[Frozen]Mock<YourInnerInterface> innerInterfaceMock,
ComplexClassWithInnerInterface sut)
{
innerInterfaceMock.Setup(x => x.Method).Result(something);
sut.DoSomething();
Assert.Equal(String.Empty, String.Empty);
}
Tenha o cuidado de sempre criar os mocks congelados antes do sut para que eles já existam quando o sut for criado e, portanto, sejam corretamente injetados.
Veja o blog de
Oi,
Eu já estava fazendo isso. Mas para 30 interfaces é muito feio tê-los nos parâmetros do método.
Seu código me lembrou que AutoMoqData não congela todas as interfaces simuladas. Portanto, parece impossível obter simulações criadas automaticamente a partir do contêiner do aparelho. Eles não são injetados por padrão, portanto, se o aparelho tiver um método como o GetInstance, ele não retornará nada para os simulados criados automaticamente. É por isso que obtenho duplicatas se congela o mock com a instância do fixture. A única maneira que vejo que funcionaria é se o sut pudesse ser atualizado com as simulações congeladas posteriores, mas isso seria feio. A maneira fácil é usar AutoMoqData para criar o IFixture, congelar e configurar mocks no método de teste e, em seguida, criar sut. Com essa configuração, posso criar um método auxiliar reutilizável para congelar e configurar simulações.
Obrigado
Obrigado @xlecoustillier pela ótima resposta. Basicamente, sugiro fazer o mesmo, pois estou constantemente seguindo esse padrão em meus testes.
Mas para 30 interfaces é muito feio tê-los nos parâmetros do método.
Bem, este argumento parece um pouco estranho. Provavelmente, há algo errado com o design do código testado se você precisar configurar 30 dependências para fazer um cenário 😟 Estou 99% @ploeh sugeriria que você revise o código antes de prosseguir, de acordo com seu conselho, é recomendável ter no máximo 3-4 dependências 😅
Portanto, parece impossível obter simulações criadas automaticamente a partir do contêiner do aparelho. Eles não são injetados por padrão, portanto, se o aparelho tiver um método como o GetInstance, ele não retornará nada para os simulados criados automaticamente.
Não estou 100% certo de que entendi toda a mensagem claramente, mas pelo que entendi você está certo. Por padrão, todos os objetos gerados são transitórios e fixture
não os preserva. Se você deseja fazer o objeto particular um singleton, você deve usar o fixture.Freeze<>()
API ou [Frozen]
atributo ou qualquer outro API adequado.
O comportamento padrão existente foi projetado para cobrir os cenários comuns e na maioria dos casos você _não quer_ ter o mesmo objeto por tipo.
Se você ainda está procurando a ajuda de nossa parte, forneça os requisitos mais precisos que você tem. Melhor, compartilhe código suficiente para demonstrar as limitações atuais e a meta que você gostaria de alcançar - isso ajudará a sincronizar melhor 😉
Obrigado.
Sim, eu sugeriria que 30 dependências são demais.
Com relação a obter as dependências injetadas, usar o atributo [Frozen]
, como @xlecoustillier sugere, é uma opção, e de fato a razão pela qual esse atributo existe originalmente.
Usar Mock.Get(sut.Dep1)
também é uma opção que uso com frequência.
Mas e se a interface for [...] injetada pelo construtor, [...] mas não acessível em sut com uma propriedade pública?
Por que não expô-lo como uma propriedade, então? O que você compõe, você também pode expor. . Não quebra o encapsulamento para expô-lo.
Sinto vontade de adicionar @ploeh especificando que a melhor abordagem é expor dependências como propriedades de classe sem enriquecer sua abstração, o que não seria nada mais do que vazar sua implementação!
@ malylemire1 Fechando isto porque parece que nenhuma assistência adicional é necessária. Informe-nos se houver mais alguma coisa em que possamos ajudá-lo 😉
Obrigado mais uma vez por levantar a questão! 👍
Comentários muito úteis
Obrigado @xlecoustillier pela ótima resposta. Basicamente, sugiro fazer o mesmo, pois estou constantemente seguindo esse padrão em meus testes.
Bem, este argumento parece um pouco estranho. Provavelmente, há algo errado com o design do código testado se você precisar configurar 30 dependências para fazer um cenário 😟 Estou 99% @ploeh sugeriria que você revise o código antes de prosseguir, de acordo com seu conselho, é recomendável ter no máximo 3-4 dependências 😅
Não estou 100% certo de que entendi toda a mensagem claramente, mas pelo que entendi você está certo. Por padrão, todos os objetos gerados são transitórios e
fixture
não os preserva. Se você deseja fazer o objeto particular um singleton, você deve usar ofixture.Freeze<>()
API ou[Frozen]
atributo ou qualquer outro API adequado.O comportamento padrão existente foi projetado para cobrir os cenários comuns e na maioria dos casos você _não quer_ ter o mesmo objeto por tipo.
Se você ainda está procurando a ajuda de nossa parte, forneça os requisitos mais precisos que você tem. Melhor, compartilhe código suficiente para demonstrar as limitações atuais e a meta que você gostaria de alcançar - isso ajudará a sincronizar melhor 😉
Obrigado.