我有一个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
答案 0 :(得分:1)
我自己没有尝试过,但它可以使用独立的事务管理器和符合XA的数据源。对于Spring 2.5,大多数样本使用JOTM以及JotmFactoryBean
和XAPool。但是在Spring 3.0中不再支持这些,Atomikos似乎是“替代”(它提供了一个独立的事务管理器和一个XA数据源)。我在下面添加了一些配置示例。
另一种方法是运行容器内测试(使用嵌入式Java EE容器,例如GlassFish v3 Embedded或类似Cargo的API)。
答案 1 :(得分:1)
@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 ...
}
}