我如何使用 junit、spring 和 JPA 测试 Optmistic Locking?

How can i test Optmistic Locking using junit, spring and JPA?

我的实体带有@version 列、daos 和junit 测试。 我如何在 junit 测试用例中引发乐观锁异常,以查看它是否得到正确处理?

我正在使用 spring 交易管理,所以我认为这让事情变得更加复杂

  1. 从 jUnit 测试方法打开一个事务并从某个 table.
  2. 中读取一行
  3. 创建一个新线程并打开另一个将读取同一行的数据库事务。
  4. 更新它,并保存到数据库中。
  5. 暂停 jUnit 测试方法使用的主线程。
  6. 修改开头读取的数据,尝试更新行。因此应该抛出乐观锁异常。

在我当前的项目中,我们必须处理 OptimisticLockException 并将其包装到自定义异常中。我们使用休眠而不是 Spring。但也许这种方式会对你有所帮助。

对于我的解决方案,您的测试中需要一个 OpenEJB-Container:

@LocalClient
public class ExampleClassTest {

    //its a self written class to bootstrap the open ejb container
    private static OpenEjbContainerStarter openEjbStarter;

    private static Context context;

    @Resource
    private UserTransaction userTransaction;

    @EJB
    private ExampleWithSaveActionFacade facade;

    @EJB
    private ExampleDAO exampleDataAccessObject;

    @BeforeClass
    public static void setUpBefore() throws Exception {
        openEjbStarter = new OpenEjbContainerStarter();
        context = openEjbStarter.startOpenEJB();
    }

    @AfterClass
    public static void shutdown() throws NamingException, SQLException {
        openEjbStarter.destroyOpenEJB();
    }

    @Before
    public void before() throws Exception {
        context.bind("inject", this);
    }

    @Test(expected = OptimisticLockException.class)
    public void testSaveSomethingWithException(){

        //get the first object you will manipulate and change the Version
        //current Version is 1
        ExampleModel example = exampleDataAccessObject.findById(1L);
        example.setSomeData("test");

        //get the second object what will cause the exception
        //current version is 1
        ExampleModel exampleOldObject = exampleDataAccessObject.findById(1L);

        // returnValue with the version number 2
        ExampleModel returnValue = facade.persistOrUpdateUser(example);

        //try to save the object with the version 1
        //throws the OptimisticLockException
        facade.persistOrUpdateUser(exampleOldObject);
    }
}