Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PR para viabilizar uso de frameworks de Mock #1

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

jeffbicca
Copy link

Sugestão de modificação no DemoiselleRunner para viabilizar o uso de framework de mocks, como por exemplo, o Mockito.

Desvincula o DemoiselleRunner dos eventos lançados pelo CDI para o Demoiselle inicializar RequestContext, SessionContext, ViewContext e ConversationContext na classe SeBootstrap. Acredito que estes escopos nem devem fazer parte de um teste JUnit e a tentativa da criação dos mesmos estavam inviabilizando o uso do DemoiselleRunner em testes de unidade com mocks.

Favor avaliar esta correção para próxima versão, @emersonsdo , @zyc , @Dancovich , @ednaraoliveira

Jefferson Bicca added 2 commits May 17, 2016 15:20
Correção de NullPointerException no método shutdown. Este método é
executado automaticamente pelo Weld ao encerrar o teste JUnit e
consequentemente, a classe SeBootstrap do package demoiselle.internal
captura o evento e ele tenta pegar uma instância null de requestContext.
AfterStartupProccess do startup.

Ao inicializar o BlockJUnit4ClassRunner com a referência do container
Weld recém inicializado já é suficiente para as injeções funcionarem.
Além disso, o lançamento dos eventos AfterStartupProccess e
AfterShutdownProcess são desnecessários para o contexto do JUnit (eles,
inclusive, podem lançar NullPointerException em alguns casos).
@Dancovich
Copy link
Member

Remover a inicialização dos escopos impede o uso de qualquer injeção cuja entidade pertença a esse escopo. Por exemplo, tente criar um teste que injeta algum filho de JPACrud ou EntityManager e verá que você vai receber um erro de escopo não ativo.

Pode ser uma boa ideia tornar o levantamento desses escopos opcional, mas remove-los inviabiliza certos testes que não usam mocks.

@zyc, o que acha?

@jeffbicca
Copy link
Author

Oi, @Dancovich e @zyc .

Efetuei um teste de execução utilizando o projeto de teste do Bookmark e executei o BookmarkBCTest que o próprio arquétipo cria e os testes passaram com sucesso com a atualização proposta no DemoiselleRunner, já que estes contextos são específicos do CDI e não tem conexão direta com JPACrud e/ou EntityManager. O Demoiselle e o CDI conseguem injetar o EntityManager normalmente sem a necessidade desses contextos.

Concordo que a verificação de null dos escopos poderia ser efetuada no próprio SeBootstrap. Acredito que essa correção também pode ser feita lá. Mas também acho que a tentativa de levantar os contextos RequestContext, SessionContext, ViewContext e ConversationContext para um teste JUnit não me parecem fazer muito sentido, pois fico com a impressão de que estes contextos fazem mais sentido no contexto web. Classes que se utilizam de atributos injetados com esse contexto poderiam ser testados unitariamente utilizando mocks ou ser testados de forma integrada utilizando o Arquillian.

@Dancovich
Copy link
Member

O motivo pelo qual seu teste funcionou é porque existe um Bootstrap no Demoiselle Core que também levanta escopos.

Faça o teste, implemente a seguinte chamada dentro de qualquer método de BookmarkBCTest:

Beans.getBeanManager().getContext(RequestScoped.class)

Se realmente nenhum escopo foi levantado esse método deve lançar uma exceção. Aqui ele retornou uma instância de TemporaryRequestContextImpl, um escopo temporário que o Demoiselle levanta durante a inicialização e depois derruba.

Agora sobre o conceito de uso de escopos durante testes é necessário estabelecermos o contexto de uso do DemoiselleRunner.

Em testes unitários "puros" concordo que levantar contextos não fazem sentido, mas a verdade é que também não faz sentido o uso de CDI ou qualquer dos outros subsistemas fornecidos por um servidor de aplicação. Em tal teste qualquer utilitário externo à unidade sendo testada deve ser "mockada". Devido a isso em tal situação o recomendado é simplesmente não usar o DemoiselleRunner.

Se a injeção de dependência é essencial para seu teste então provavelmente não se trata de um teste unitário, mas de integração. Um exemplo típico é testar se o sistema de paginação usando a classe Pagination funciona, o teste pode consistir em injetar seu ManagedBean que define a página atual desejada e injetar seu DAO e verificar se o Pagination manteve as configurações ao ser injetado no DAO. O sistema de paginação no Demoiselle é RequestScoped então é necessário levantar esse escopo para testar corretamente esse sistema.

O Arquillian pode ser usado nesses casos como você disse. Na verdade o Demoiselle JUnit surgiu quando o Arquillian ainda não era maduro o suficiente para ser usado em projetos em produção e era necessário um sistema que levantasse um contexto CDI "light" para executar tais testes de integração. Seu valor ainda existe para pequenos testes de integração onde a configuração do Arquillian seriam muito custosa e onde tudo que precisamos é do sistema de injeção funcionando.

Em todo caso é interessante explorar a possibilidade de tornar o levantamento de escopos opcional. Em certos testes precisamos do sistema de injeção mas não de escopos ou até mesmo podemos desejar testar se certos sistemas podem ser usados sem um escopo ativo, por exemplo quando desejamos testar se um método pode ser chamado durante o evento @Startup (o do EJB, não o do Demoiselle).

Poderiamos discutir uma arquitetura para tal, talvez uma anotação opcional no teste? O que acham @zyc @emersonsdo @ednaraoliveira @lusabo ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants