如何获取JPA / JTA DAO集成测试的JNDI数据源?

时间:2010-06-09 17:59:12

标签: jpa datasource integration-testing jndi jta

我有一个JPA应用程序,它在persistence.xml中指定了JTA事务。无论出于何种原因,我发现在使用JTA时,您还必须在persistence.xml中指定JNDI数据源。这很好,除非您尝试在容器外部进行集成测试并且JNDI不可用。

我的问题是:

a)无论如何都要将jdbc数据源注入我的JTA事务管理器? b)如果没有,如何在集成测试期间处理JNDI查找?

编辑:启动集成测试时遇到的错误是:

 Caused by: org.springframework.......DataSourceLookupFailureException:
 Failed to look up JNDI DataSource with name 'java:comp/env/jdbc/myAppDataSource';
 nested exception is javax.naming.NoInitialContextException: Need to specify
 class name in environment or system property, or as an applet parameter,
 or in an application resource file:  java.naming.factory.initial

2 个答案:

答案 0 :(得分:1)

我自己没有尝试过,但它可以使用独立的事务管理器和符合XA的数据源。对于Spring 2.5,大多数样本使用JOTM以及JotmFactoryBeanXAPool。但是在Spring 3.0中不再支持这些,Atomikos似乎是“替代”(它提供了一个独立的事务管理器和一个XA数据源)。我在下面添加了一些配置示例。

另一种方法是运行容器内测试(使用嵌入式Java EE容器,例如GlassFish v3 Embedded或类似Cargo的API)。

资源

答案 1 :(得分:1)

我自己遇到了类似的问题。我正在使用Spring和JPA并将我的数据库指定为JNDI名称。最终我决定用Mockito模仿JNDI。这很简单。我是这样做的:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"classpath:spring-config.xml"})
public class MyTestClass {

    private static final InitialContextFactoryBuilder contextFactoryBuilder = mock(InitialContextFactoryBuilder.class);
    private static final InitialContextFactory contextFactory = mock(InitialContextFactory.class);
    private static final Context context = mock(Context.class);
    private static final NameParser parser = mock(NameParser.class);
    private static final Name dbName = mock(Name.class);
    // This is the Datasource implementation from the H2 database
    private static final JdbcDataSource temporaryDbForTesting = new JdbcDataSource();

    @BeforeClass
    public static void setupMockJndi() throws NamingException {
        NamingManager.setInitialContextFactoryBuilder(contextFactoryBuilder);
        when(contextFactoryBuilder.createInitialContextFactory(any(Hashtable.class))).thenReturn(contextFactory);
        when(contextFactory.getInitialContext(any(Hashtable.class))).thenReturn(context);
        when(context.getNameParser(any(String.class))).thenReturn(parser);
        when(parser.parse("GatewayDbDataSource")).thenReturn(dbName);
        when(context.lookup(dbName)).thenReturn(temporaryDbForTesting);

        temporaryDbForTesting.setURL("jdbc:h2:~/test2");
        temporaryDbForTesting.setUser("sa");
        temporaryDbForTesting.setPassword("");
    }

    @Autowired
    private org.zzz.DomainObject toTest;

    @Test
    public void testPasswordChecking() {
        assertNotNull("There wasn't an object to test. Spring is broken!", toTest);
        // ... assertions and such ...
    }

}