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

发布于 2024-08-18 04:57:27 字数 2693 浏览 1 评论 0原文

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

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

@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 方法进行 2 个并行调用。因此,我创建了一个实现 Callable 的内部类,以便在 2 个不同的线程中调用我的方法并希望并行运行它们。
但是,这样做似乎会使 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;   
    } 
}

有没有办法进行回滚???

感谢您的帮助。

问候,

菲利普

I'm trying to create integration tests for a legacy application deployed on Weblogic 8.1 using a subclass of AbstractTransactionalJUnit4SpringContextTests.

My test method has the following annotations :

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

My test class also references beans of type org.springframework.ejb.access.SimpleRemoteStatelessSessionProxyFactoryBean, which proxy the EJBs deployed on my weblogic server.

When I call methods on this proxy bean in a sequencial manner in my test method, the transaction rolls back correctly at the end of the test.

e.g. :

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

However, I would like to make 2 parallel calls to the same EJB method. Therefore I've made an inner class that implements Callable, in order to call my methods in 2 different Threads and hope to run those in parallel.
However, doing this seems to make the ejb methods to be called outside my transaction, and nothing is rolled back.

Here is what the full test class would like when I run the method calls in parallel :

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;   
    } 
}

Is there a way to make this rollback ???

Thanks for your help.

Regards,

Philippe

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

—━☆沉默づ 2024-08-25 04:57:27

不会自动,不会。问题是两个额外的线程不参与事务,因此它们的操作不会回滚。

两次并行执行的目的是什么?如果您的目标是这样的话,您不太可能能够使用此方法测试并发问题。

编辑:问题在于测试并发问题非常困难,因为您的测试充其量只是概率性的 - 成功或失败取决于微妙的计时问题,而这些问题可能只会在第十亿次运行时才会出现。请参阅这篇服务器端文章,了解基础知识的详细摘要。

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

Not automatically, no. The problem is that the two extra threads don't participate in the transaction, hence their actions don't rollback.

What is the purpose of the two parallel executions? You will unlikely be able to test for concurrency issues with this approach, if that is what you're aiming for.

Edit: The problem is that testing for concurrency issues is very hard, because your tests are, at best, probabilistic ­­­­– success or failure depend on subtle timing issues that may only surface on the billionth run. See this Serverside article for a good summary of the basics.

The rule of thumb should be to avoid hand-coding threading whenever possible, as it is hard to get right and difficult to test. If you can, avoid shared state between threads, and if there is no way around it, rely on the concurrent data structures and asynchronous executors from the java.util.concurrent package.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文