Spring测试:测试方法执行后事务未回滚

3

我正在尝试为部署在Weblogic 8.1上的遗留应用程序创建集成测试,使用AbstractTransactionalJUnit4SpringContextTests的子类。

我的测试方法具有以下注释:

@Test
@Rollback(true)
public void testDeployedEJBCall throws Exception {...}

我的测试类还引用了类型为org.springframework.ejb.access.SimpleRemoteStatelessSessionProxyFactoryBean的bean,这些代理weblogic服务器上部署的EJB。

当我在测试方法中按顺序调用此代理bean上的方法时,事务会在测试结束时正确回滚。

例如:

@Test
@Rollback(true)
public void testDeployedEJBCall throws Exception {
    Long result1 = myejb.method(100L);
    Long result2 = myejb.method(200L);
    ...
}

然而,我希望对同一个EJB方法进行两个并行调用。因此,我创建了一个实现Callable接口的内部类,以便在两个不同的线程中调用我的方法,并希望并行运行这些方法。
然而,这样做似乎会使ejb方法在我的事务之外被调用,且没有任何回滚。

当我并行运行方法调用时,完整的测试类如下:

import org.springframework.test.annotation.*;

@RunWith(SpringJUnit4ClassRunner.class)
@Transactional
@ContextConfiguration(locations = {"classpath:path/to/tests-config.xml"})
@TransactionConfiguration(defaultRollback=true)
public final class IntegrationTests extends AbstractTransactionalJUnit4SpringContextTests {
    @Autowired
    protected JndiTemplate jndiTemplate;
    @Resource
    protected Proxy myEJB;

    public IntegrationTests() {
        super();
        this.logger = Logger.getLogger(IntegrationTests.class);
    }

    @Test
    @Rollback(true)
    public void testDeployedEJBCall() throws Exception {
        // Create a thread pool for parallel execution. 
        ExecutorService exec = Executors.newFixedThreadPool(2);

        // Prepare the tasks for parallel execution
        List<CallEJBTask> tasks = new ArrayList<CallEJBTask>();
        tasks.add(new CallEJBTask(100L, this.myEJB));
        tasks.add(new CallEJBTask(200L, this.myEJB));

        // Execute all pending tasks in the exec Threadpool
        List<Future<Long>> results = exec.invokeAll(tasks);

        // Get the results of each task
        Long result1 = results.get(0).get();
        Long result2 = results.get(1).get();

        ...
    }
}

private class CallEBJTask implements Callable<Long> {
    private final Long valueToTest;
    private final MyEJB myEJB;

    public CallEJBTask(Long valueToTest, Proxy myEJBProxy)
        this.valueToTest = valueToTest;
        this.myEJB = (MyEJB)myEJBProxy;
    }

    public Long call() throws Exception {
        return getResult();
    }

    public Long getResult() {
        Long result = null;

        try {
            result = this.myEJB.method(this.patient);

        } catch (Exception e) {
            ...
        }
        return result;   
    } 
}

有没有办法回滚这个操作?谢谢你的帮助。
祝好,
Philippe
1个回答

2

不会自动执行回滚,因为两个额外的线程不参与事务,所以它们的操作不会回滚。

这两个并行执行的目的是什么?如果您的目标是测试并发问题,您可能无法使用此方法进行测试。

编辑:测试并发问题很困难,因为您的测试最多只是概率性的——成功或失败取决于可能只在第十亿次运行时才出现的微妙时机问题。请参阅此Serverside文章,了解基础知识的良好摘要。

经验法则应该是尽可能避免手动编码线程,因为很难正确处理并且难以测试。如果可以的话,请避免在线程之间共享状态,并且如果没有其他办法,请依赖于java.util.concurrent包中的并发数据结构和异步执行程序。


是的,这正是我所追求的...那么我应该使用什么方法呢?我考虑的另一个可能性是在两台不同的机器上使用@Repeat(someBigNumber)来运行相同的测试在我的测试方法头中...那样行吗? - Philippe
嗯...我看过那篇文章...这不就是我在我的示例中正在做的吗? - Philippe

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接