Como você testa uma função privada no angular 2?
class FooBar {
private _status: number;
constructor( private foo : Bar ) {
this.initFooBar();
}
private initFooBar(){
this.foo.bar( "data" );
this._status = this.fooo.foo();
}
public get status(){
return this._status;
}
}
A solução que encontrei
Coloque o próprio código de teste dentro do fechamento ou Adicionar código dentro do fechamento que armazena referências às variáveis locais em objetos existentes no escopo externo.
Posteriormente, retire o código de teste usando uma ferramenta. http://philipwalton.com/articles/how-to-unit-test-private-functions-in-javascript/
Por favor, sugira-me uma maneira melhor de resolver este problema, se você tiver feito algum?
PS
A maior parte da resposta para um tipo semelhante de pergunta como esta não fornece uma solução para o problema, é por isso que estou fazendo esta pergunta
A maioria dos desenvolvedores diz que você não testa funções privadas, mas eu não digo que elas estão erradas ou corretas, mas há necessidade de meu caso testar particular.
fonte
Respostas:
Estou com você, mesmo que seja um bom objetivo "testar unicamente a API pública", há momentos em que isso não parece tão simples e você sente que está escolhendo entre comprometer a API ou os testes de unidade. Você já sabe disso, já que é exatamente isso que você está pedindo para fazer, então não vou entrar nisso. :)
No TypeScript, descobri algumas maneiras de acessar membros privados para fins de teste de unidade. Considere esta classe:
Mesmo que TS restringe o acesso a membros da classe usando
private
,protected
,public
, a JS compilado não tem membros privados, uma vez que esta não é uma coisa em JS. É puramente usado para o compilador TS. Para isso:Você pode afirmar
any
e evitar que o compilador o avise sobre restrições de acesso:O problema dessa abordagem é que o compilador simplesmente não faz ideia do que você está fazendo certo
any
, para que você não obtenha os erros de tipo desejados:Obviamente, isso tornará a refatoração mais difícil.
Você pode usar o array access (
[]
) para acessar os membros privados:Embora pareça estranho, o TSC validará os tipos como se você os tivesse acessado diretamente:
Para ser sincero, não sei por que isso funciona.Aparentemente, essa é uma "escotilha de escape" intencional para fornecer acesso a membros privados sem perder a segurança do tipo. É exatamente o que eu acho que você deseja para o seu teste de unidade.Aqui está um exemplo de trabalho no TypeScript Playground .
Editar para TypeScript 2.6
Outra opção que alguns gostam é usar
// @ts-ignore
( adicionado no TS 2.6 ) que simplesmente suprime todos os erros na seguinte linha:O problema disso é que, bem, suprime todos os erros na seguinte linha:
Pessoalmente, considero
@ts-ignore
um cheiro de código e, como dizem os documentos:fonte
as any
: você perde toda a verificação de tipo.Você pode chamar métodos privados . Se você encontrou o seguinte erro:
basta usar
// @ts-ignore
:fonte
as any
que você perde qualquer verificação de tipo, na verdade você perde qualquer verificação de tipo em toda a linha.Como a maioria dos desenvolvedores não recomenda testar a função privada , por que não testá-la?
Por exemplo.
YourClass.ts
TestYourClass.spec.ts
Graças a @Aaron, @Thierry Templier.
fonte
Não escreva testes para métodos particulares. Isso anula o ponto dos testes de unidade.
Exemplo
O teste desse método não precisará ser alterado se posteriormente a implementação for alterada, mas a
behaviour
API pública permanecer a mesma.Não torne públicos métodos e propriedades apenas para testá-los. Isso geralmente significa que:
fonte
O objetivo de "não testar métodos particulares" é realmente Testar a classe como alguém que a usa .
Se você possui uma API pública com 5 métodos, qualquer consumidor de sua classe pode usá-los e, portanto, deve testá-los. Um consumidor não deve acessar os métodos / propriedades particulares de sua classe, o que significa que você pode alterar membros privados quando a funcionalidade exposta ao público permanecer a mesma.
Se você confiar na funcionalidade extensível interna, use em
protected
vez deprivate
.Observe que
protected
ainda é uma API pública (!) , Usada apenas de forma diferente.O teste de unidade protegeu as propriedades da mesma maneira que um consumidor as usaria, via subclassificação:
fonte
Isso funcionou para mim:
Ao invés de:
Este:
fonte
Desculpem o necro deste post, mas sinto-me compelido a considerar algumas coisas que parecem não ter sido tocadas.
Em primeiro lugar - quando nos encontramos precisando de acesso a membros particulares de uma classe durante o teste de unidade, geralmente é uma bandeira vermelha grande e ridícula que brincamos em nossa abordagem estratégica ou tática e violamos inadvertidamente o diretor de responsabilidade única pressionando comportamento onde não pertence. Sentir a necessidade de acessar métodos que nada mais são do que uma sub-rotina isolada de um procedimento de construção é uma das ocorrências mais comuns; no entanto, é como se seu chefe esperasse que você aparecesse para o trabalho pronto para ir e também tenha alguma necessidade perversa de saber por que rotina matinal você passou para entrar nesse estado ...
O outro exemplo mais comum desse acontecimento é quando você tenta testar a proverbial "classe divina". É um tipo especial de problema por si só, mas sofre do mesmo problema básico por precisar conhecer detalhes íntimos de um procedimento - mas isso está saindo do tópico.
Neste exemplo específico, atribuímos efetivamente a responsabilidade de inicializar totalmente o objeto Bar ao construtor da classe FooBar. Na programação orientada a objetos, um dos principais inquilinos é que o construtor é "sagrado" e deve ser protegido contra dados inválidos que invalidariam seu próprio estado interno e o deixariam preparado para falhar em outro lugar a jusante (no que poderia ser muito profundo). pipeline.)
Falhamos em fazer isso aqui, permitindo que o objeto FooBar aceite uma barra que não está pronta no momento em que o FooBar é construído e compensamos com uma espécie de "invasão" do objeto FooBar para resolver os problemas por conta própria mãos
Isso é o resultado de uma falha em aderir a outro conteúdo da programação orientada a objetos (no caso de Bar), que significa que o estado de um objeto deve estar totalmente inicializado e pronto para lidar com as chamadas recebidas de seus membros públicos imediatamente após a criação. Agora, isso não significa imediatamente após o construtor ser chamado em todas as instâncias. Quando você tem um objeto que possui muitos cenários de construção complexos, é melhor expor os setters a seus membros opcionais a um objeto implementado de acordo com um padrão de design de criação (Factory, Builder, etc ...) os últimos casos,
No seu exemplo, a propriedade "status" da barra não parece estar em um estado válido no qual um FooBar possa aceitá-la - portanto, a FooBar faz algo para corrigir esse problema.
O segundo problema que estou vendo é que parece que você está tentando testar seu código em vez de praticar o desenvolvimento orientado a testes. Esta é definitivamente a minha opinião neste momento; mas, esse tipo de teste é realmente um anti-padrão. O que você acaba fazendo é cair na armadilha de perceber que possui problemas essenciais de design que impedem que seu código seja testável após o fato, em vez de gravar os testes necessários e, posteriormente, programar os testes. De qualquer forma, você enfrenta o problema, ainda deve ter o mesmo número de testes e linhas de código se realmente tiver conseguido uma implementação do SOLID. Então - por que tentar fazer uma engenharia reversa em código testável quando você pode apenas resolver o problema no início de seus esforços de desenvolvimento?
Se você tivesse feito isso, teria percebido muito antes que teria que escrever um código bastante nojento para testar seu design e teria tido a oportunidade desde o início de realinhar sua abordagem, mudando o comportamento para implementações que são facilmente testáveis.
fonte
Concordo com @toskv: eu não recomendaria fazer isso :-)
Mas se você realmente deseja testar seu método privado, pode estar ciente de que o código correspondente para o TypeScript corresponde a um método do protótipo da função do construtor. Isso significa que ele pode ser usado em tempo de execução (enquanto você provavelmente terá alguns erros de compilação).
Por exemplo:
será transpilado para:
Veja este artigo: https://plnkr.co/edit/calJCF?p=preview .
fonte
Como muitos já declararam, por mais que você queira testar os métodos particulares, não deve hackear seu código ou transpiler para fazê-lo funcionar. Atualmente, o TypeScript negará a maioria dos hacks que as pessoas forneceram até agora.
Solução
TLDR ; se um método deve ser testado, você deve dissociar o código em uma classe que possa expor o método a ser público a ser testado.
O motivo de você ter o método privado é que a funcionalidade não pertence necessariamente a ser exposta por essa classe e, portanto, se a funcionalidade não pertencer a ela, ela deve ser dissociada em sua própria classe.
Exemplo
Encontrei este artigo que explica muito bem como você deve lidar com o teste de métodos particulares. Ele ainda cobre alguns dos métodos aqui e como eles são implementações ruins.
https://patrickdesjardins.com/blog/how-to-unit-test-private-method-in-typescript-part-2
Nota : este código foi retirado do blog vinculado acima (estou duplicando caso o conteúdo por trás do link seja alterado)
Antes Depois defonte
chamar método privado usando colchetes
Arquivo Ts
arquivo spect.ts
fonte
A resposta de Aaron é a melhor e está funcionando para mim :) Eu votaria, mas infelizmente não posso (falta de reputação).
Devo dizer que testar métodos particulares é a única maneira de usá-los e ter um código limpo do outro lado.
Por exemplo:
Faz muito sentido não testar todos esses métodos de uma só vez, porque precisaríamos zombar desses métodos privados, que não podemos zombar porque não podemos acessá-los. Isso significa que precisamos de muita configuração para um teste de unidade para testar isso como um todo.
Dito isso, a melhor maneira de testar o método acima com todas as dependências é um teste completo, porque aqui é necessário um teste de integração, mas o teste E2E não ajudará se você estiver praticando TDD (Test Driven Development), mas testando qualquer método será.
fonte
Essa rota que eu tomo é aquela em que crio funções fora da classe e atribuo a função ao meu método privado.
Agora não sei que tipo de regras de OOP estou violando, mas, para responder à pergunta, é assim que testo métodos privados. Congratulo-me com alguém para aconselhar sobre os prós e contras disso.
fonte