O GlassFish incorporado ignora os resources de teste do Maven

Eu tenho vários beans de session para os quais escrevi testes de unidade. Eu configurei o Maven para include um persistence.xml no diretório src / main / resources / META-INF que se refere a um database MySQL local para fins de desenvolvimento. Eu tenho outro persistence.xml no diretório src / test / resources / META-INF que se refere ao database __default incorporado do Derby. Os testes são implantados em um contêiner GlassFish 3.1 incorporado.

Quando eu executo os testes, no entanto, recebo o seguinte erro:

java.lang.RuntimeException: javax.naming.NamingException: Lookup failed for 'jdbc/mylog' 

jdbc / mylog é o database MySQL ao qual a unidade de persistência no diretório principal se refere. Obviamente, está ignorando a unidade de persistência no diretório de teste, mas não tenho a menor idéia do motivo.

Maven está definindo o caminho de class corretamente, até onde eu posso dizer, com classs de teste antes das classs e uma espiada no diretório target / test-classs / META-INF real revela que ele copiou o Derby correto e integrado, unidade de persistência.

 [DEBUG] Test Classpath : [DEBUG] C:\Users\Laurens\Documents\Projects\Mylog\target\test-classs [DEBUG] C:\Users\Laurens\Documents\Projects\Mylog\target\classs [DEBUG] C:\Users\Laurens\.m2\repository\org\eclipse\persistence\eclipselink\2.2.0\eclipselink-2.2.0.jar [DEBUG] C:\Users\Laurens\.m2\repository\org\eclipse\persistence\javax.persistence\2.0.3\javax.persistence-2.0.3.jar [DEBUG] C:\Users\Laurens\.m2\repository\org\eclipse\persistence\org.eclipse.persistence.jpa.modelgen.processor\2.2.0\org.eclipse.persistence.jpa.modelgen.processor-2.2.0.jar [DEBUG] C:\Users\Laurens\.m2\repository\org\glassfish\extras\glassfish-embedded-all\3.1\glassfish-embedded-all-3.1.jar [DEBUG] C:\Users\Laurens\.m2\repository\javax\javaee-web-api\6.0\javaee-web-api-6.0.jar [DEBUG] C:\Users\Laurens\.m2\repository\junit\junit\4.8.1\junit-4.8.1.jar 

Qualquer dica sobre como ter GlassFish usar a unidade de persistência adequada muito apreciada! Obrigado!

Ao executar testes usando Glassfish incorporado, o provedor JPA não usa o caminho de class exibido na linha de comando, antes de executar a meta maven-surefire-plugin (que é usada para executar a fase de teste). O Glassfish incorporado implementa os artefatos que estão disponíveis como parte de um escopo de teste, como um ScatteredArchive . Esse archive disperso geralmente é criado no diretório java.io.tmpdir normalmente com o nome gfembedtmp , a menos que a configuração Glassfish incorporada tenha especificado a localização de uma raiz de instalação do Glassfish e um domínio Glassfish.

Quando o domínio Glassfish incorporado é preparado com o archive disperso implantado, os arquivos a serem implantados geralmente são copiados em um diretório explodido que abriga todas as classs (incluindo todas as dependencies) exigidas pelo aplicativo. Esse diretório geralmente está presente no GF_EMBED_DOMAIN_HOME/applications/ . Os arquivos persistence.xml de seus diretórios src/main/resources/META-INF e src/test/resources/META-INF são copiados aqui no diretório /META-INF . Escusado será dizer, aquele que é copiado por último, ou aquele que não é substituído é aquele que é usado pelo provedor de JPA durante os testes. Isso sempre acontece de ser o arquivo em src/main/resources/META-INF .

Você pode superar essa situação de duas maneiras:

1. Usando um arquivo de configuração de domínio Glassfish personalizado

Você pode especificar um arquivo de configuração de domínio ( domain.xml ) que contenha a definição da fonte de dados para jdbc/mylog . Isto é o que eu faço atualmente pois é muito flexível e o arquivo de configuração do domínio pode conter outras configurações também. O arquivo de configuração precisa ser especificado como parte da configuração de teste da seguinte maneira:

 Map props = new HashMap(); props.put("org.glassfish.ejb.embedded.glassfish.installation.root", "./glassfish-install/glassfish"); container = EJBContainer.createEJBContainer(props); context = container.getContext(); datasource = (DataSource) context.lookup("jdbc/mylog"); //You can lookup the datasource too, to confirm that your setup is successful. 

O diretório de glassfish-install mencionado anteriormente e seu glassfish subdiretório estão presentes na raiz do projeto Maven (e também verificados no version control); O diretório glassfish deve conter uma estrutura de diretório de domain1/config para representar a estrutura de diretórios do domínio Glassfish do nome domain1 . A estrutura do projeto pode ser vista na imagem abaixo. Os outros arquivos relacionados (JARs do adaptador de resources JDBC e similares) podem ser obtidos de um diretório de instalação do Glassfish, mas normalmente também podem ser colocados no local correto pelo runtime Glassfish incorporado, se configurado corretamente.

Localização do arquivo de configuração do domínio Glassfish

O conteúdo do arquivo de configuração do domínio Glassfish é diferente do arquivo padrão usado pelo Glassfish, exceto pela configuração da fonte de dados e do conjunto de conexões (as inputs relevantes adicionadas no meu caso onde realizo os testes de integração foram postadas abaixo):

      ...               ...         ... ... 

O arquivo domain.xml padrão pode ser baixado do site java.net e modificado, no caso de você desejar manter as alterações o mínimo possível, em vez de copiá-las de uma instalação do Glassfish.

2. Copiando sobre os arquivos persistence.xml

É possível adicionar metas ao arquivo POM do Maven, fazer backup e copiar o arquivo persistence.xml de src/test/resources/META-INF para src/main/resources/META-INF , antes da fase de test . Após a conclusão da fase de teste, o original é restaurado. Não entrarei em detalhes sobre isso, já que uma solução semelhante já foi discutida em uma questão relacionada ao StackOverflow . Eu não usei essa abordagem para testes de integração, pois exigia que as mudanças fossem feitas além daquelas que podem ser realizadas no persistence.xml , como a criação de um domínio personalizado. Eu o uso para testes unitários, no entanto, devido ao fato de que o provedor JPA buscará o arquivo persistence.xml de target/classs vez de target/test-classs , apesar do último aparecer primeiro na ordem do classpath. Se você usar o Hibernate como seu provedor JPA, habilitar o log TRACE para o org.hibernate.ejb logs org.hibernate.ejb (como a class Ejb3Configuration é responsável por realizar a busca) convenceria você de que o arquivo nas test-classs não será selecionado.


Nota:

A maior parte da resposta assume GlassFish 3.1, mas também pode ser válida para versões futuras.

Por “recipiente glassfish incorporado”, você quer dizer um plugin maven que roda glassfish para você? O classpath de um plugin maven é diferente e gerenciado de maneira diferente do classpath do teste maven. Você pode precisar estar trabalhando com um caminho de class diferente.

Esta resposta pode soar bobo, mas eu estava procurando uma maneira que me permite executar esses testes do eclipse por Run As -> JUnit Test . Foi assim que eu fiz:

 @BeforeClass public static void setUp() throws IOException { Files.copy(new File("target/test-classs/META-INF/persistence.xml"), new File("target/classs/META-INF/persistence.xml")); // ... } 

Eu estou apenas copiando o teste / persistence.xml para classs / persistence.xml. Isso funciona.