2

我有一个 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
4

2 回答 2

1

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

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

资源

于 2010-06-10T00:04:14.793 回答
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 ...
    }

}
于 2012-07-09T20:18:55.407 回答