Preloader image

Introdução

CDI é uma revolução para o mundo Java EE. Está especificação é a melhor para evitar acoplamento entre classes.

Este exemplo simplesmente pretende substituir ligações em tempo de execução para simplificar o trabalho de mocking.

Aqui usamos dois tipos de mocks:

1) um mock com nenhuma implementação no classloader

2) um mock com uma implementação no classloader

A resposta mock do CDI é chamada de alternative.

Anotando com o @Alternative uma classe significa que será usado como implementação se não houver outra implementação ou se for forçado (através do META-INF/beans.xml).

Explicação do Código

Código Principal

Nós usamos um EJB Journey para modelar um journey onde o vehicle e society pode mudar. Aqui um EJB é usado por que isto simplifica o teste. Uma journey envolve a informação de vehicle e society .

Nós definimos duas interfaces para injetar no EJB Journey:` Vehicle` e Society.

Finalmente, adicionamos uma implementação para a interface Society:` LowCostCompanie`.

Se paramos aqui, o objeto Journey não poderá ser criado porque não há uma implementação Vehicle acessível.

se tivermos uma implementação de Vehicle, a Society injetada deverá ser LowCostCompanie.

Código de Teste

O objetivo aqui é para testar o nosso EJB Journey. Portanto, temos que fornecer uma implementação de Vehicle:` SuperCar`.

Queremos forçar a interface Society a ser a implementação do AirOpenEJB para o nosso teste.

Uma solução poderia ser simplesmente adicionar a anotação @ Alternative no` AirOpenEJB` e ativá-la através do arquivo META-INF / beans.xml.

Aqui queremos escrever um código mais explícito. Então, queremos substituir a anotação @Alternative por uma` @Mock.

Então nós definimos uma anotação @Mock para classes, resolvíveis em tempo de execução como um estereótipo (` @Stereotype`) que substitui o @Alternative.

Aqui a anotação:

 @Stereotype // we define a stereotype
 @Retention(RUNTIME) // resolvable at runtime
 @Target(TYPE) // this annotation is a class level one
 @Alternative // it replace @Alternative
 public @interface Mock {}
você pode adicionar mais anotações CDI após @Alternative e obterá o comportamento esperado (o escopo para a instância).

Então agora temos a nossa anotação @ Mock, que é um estereótipo capaz de substituir a anotação` @ Alternative` quando adicionado às nossas mocks.

Se você executar isso agora, nós receberemos está exceção:

 javax.enterprise.inject.UnsatisfiedResolutionException: Api type [org.superbiz.cdi.stereotype.Vehicle] is not found with the qualifiers
 Qualifiers: [@javax.enterprise.inject.Default()]
 for injection into Field Injection Point, field name :  vehicle,
 Bean Owner : [Journey, Name:null, WebBeans Type:ENTERPRISE, API Types:[java.lang.Object,org.superbiz.cdi.stereotype.Journey],
 Qualifiers:[javax.enterprise.inject.Any,javax.enterprise.inject.Default]]

Isso significa que o estereótipo não está ativado. Para fazer isso basta adicioná-lo ao seu META-INF / beans.xml:

 <alternatives>
   <stereotype>org.superbiz.cdi.stereotype.Mock</stereotype>
 </alternatives>
se você não especificar AirOpenEJB como` @ Alternative` (feito através de nossa anotação mock) você receberá está exceção:
 Caused by: javax.enterprise.inject.AmbiguousResolutionException:
 There is more than one api type with : org.superbiz.cdi.stereotype.Society with qualifiers :
 Qualifiers: [@javax.enterprise.inject.Default()] for injection into Field Injection Point, field name :  society,
 Bean Owner : [Journey, Name:null, WebBeans Type:ENTERPRISE,
 API Types:[org.superbiz.cdi.stereotype.Journey,java.lang.Object],
 Qualifiers:[javax.enterprise.inject.Any,javax.enterprise.inject.Default]]
 found beans:
 AirOpenEJB, Name:null, WebBeans Type:MANAGED,
API Types:[org.superbiz.cdi.stereotype.Society,org.superbiz.cdi.stereotype.AirOpenEJB,java.lang.Object],
Qualifiers:[javax.enterprise.inject.Any,javax.enterprise.inject.Default]
 LowCostCompanie, Name:null, WebBeans Type:MANAGED,
API Types:[org.superbiz.cdi.stereotype.Society,org.superbiz.cdi.stereotype.LowCostCompanie,java.lang.Object],
Qualifiers:[javax.enterprise.inject.Any,javax.enterprise.inject.Default]

o que significa simplesmente que duas implementações estão disponíveis para o mesmo ponto de injeção (Journey.society).

Conclusão

Com o CDI é realmente fácil definir anotações com um forte significado. Você pode definir anotações de negócios ou simplesmente anotações técnicas para simplificar seu código (como fizemos com a anotação mock).

se você usou qualificadores para injetar objetos Society você poderia ter colocado todos esses qualificadores em a classe mock ou definiu uma anotação @SocietyMock para poder injetar a mesma implementação para todos os qualificadores em seus testes.

Saída

 Running org.superbiz.cdi.stereotype.StereotypeTest
 Apache OpenEJB 7.0.0-SNAPSHOT    build: 20111030-07:54
 http://tomee.apache.org/
 INFO - openejb.home = /opt/dev/openejb/openejb-trunk/examples/cdi-alternative-and-stereotypes
 INFO - openejb.base = /opt/dev/openejb/openejb-trunk/examples/cdi-alternative-and-stereotypes
 INFO - Using 'javax.ejb.embeddable.EJBContainer=true'
 INFO - Configuring Service(id=Default Security Service, type=SecurityService, provider-id=Default Security Service)
 INFO - Configuring Service(id=Default Transaction Manager, type=TransactionManager, provider-id=Default Transaction Manager)
 INFO - Found EjbModule in classpath: /opt/dev/openejb/openejb-trunk/examples/cdi-alternative-and-stereotypes/target/test-classes
 INFO - Found EjbModule in classpath: /opt/dev/openejb/openejb-trunk/examples/cdi-alternative-and-stereotypes/target/classes
 INFO - Beginning load: /opt/dev/openejb/openejb-trunk/examples/cdi-alternative-and-stereotypes/target/test-classes
 INFO - Beginning load: /opt/dev/openejb/openejb-trunk/examples/cdi-alternative-and-stereotypes/target/classes
 INFO - Configuring enterprise application: /opt/dev/openejb/openejb-trunk/examples/cdi-alternative-and-stereotypes
 INFO - Configuring Service(id=Default Managed Container, type=Container, provider-id=Default Managed Container)
 INFO - Auto-creating a container for bean cdi-alternative-and-stereotypes_test.Comp: Container(type=MANAGED, id=Default Managed Container)
 INFO - Configuring Service(id=Default Singleton Container, type=Container, provider-id=Default Singleton Container)
 INFO - Auto-creating a container for bean Journey: Container(type=SINGLETON, id=Default Singleton Container)
 INFO - Enterprise application "/opt/dev/openejb/openejb-trunk/examples/cdi-alternative-and-stereotypes" loaded.
 INFO - Assembling app: /opt/dev/openejb/openejb-trunk/examples/cdi-alternative-and-stereotypes
 INFO - Jndi(name="java:global/cdi-alternative-and-stereotypes/cdi-alternative-and-stereotypes_test.Comp!org.apache.openejb.BeanContext$Comp")
 INFO - Jndi(name="java:global/cdi-alternative-and-stereotypes/cdi-alternative-and-stereotypes_test.Comp")
 INFO - Jndi(name="java:global/cdi-alternative-and-stereotypes/cdi-alternative-and-stereotypes.Comp!org.apache.openejb.BeanContext$Comp")
 INFO - Jndi(name="java:global/cdi-alternative-and-stereotypes/cdi-alternative-and-stereotypes.Comp")
 INFO - Jndi(name="java:global/cdi-alternative-and-stereotypes/Journey!org.superbiz.cdi.stereotype.Journey")
 INFO - Jndi(name="java:global/cdi-alternative-and-stereotypes/Journey")
 INFO - Jndi(name="java:global/EjbModule162291475/org.superbiz.cdi.stereotype.StereotypeTest!org.superbiz.cdi.stereotype.StereotypeTest")
 INFO - Jndi(name="java:global/EjbModule162291475/org.superbiz.cdi.stereotype.StereotypeTest")
 INFO - Created Ejb(deployment-id=cdi-alternative-and-stereotypes_test.Comp, ejb-name=cdi-alternative-and-stereotypes_test.Comp, container=Default Managed Container)
 INFO - Created Ejb(deployment-id=cdi-alternative-and-stereotypes.Comp, ejb-name=cdi-alternative-and-stereotypes.Comp, container=Default Managed Container)
 INFO - Created Ejb(deployment-id=org.superbiz.cdi.stereotype.StereotypeTest, ejb-name=org.superbiz.cdi.stereotype.StereotypeTest, container=Default Managed Container)
 INFO - Created Ejb(deployment-id=Journey, ejb-name=Journey, container=Default Singleton Container)
 INFO - Started Ejb(deployment-id=cdi-alternative-and-stereotypes_test.Comp, ejb-name=cdi-alternative-and-stereotypes_test.Comp, container=Default Managed Container)
 INFO - Started Ejb(deployment-id=cdi-alternative-and-stereotypes.Comp, ejb-name=cdi-alternative-and-stereotypes.Comp, container=Default Managed Container)
 INFO - Started Ejb(deployment-id=org.superbiz.cdi.stereotype.StereotypeTest, ejb-name=org.superbiz.cdi.stereotype.StereotypeTest, container=Default Managed Container)
 INFO - Started Ejb(deployment-id=Journey, ejb-name=Journey, container=Default Singleton Container)
 INFO - Deployed Application(path=/opt/dev/openejb/openejb-trunk/examples/cdi-alternative-and-stereotypes)
 INFO - Undeploying app: /opt/dev/openejb/openejb-trunk/examples/cdi-alternative-and-stereotypes