[英]How to unit test pessimistic locking with Spring Boot + Spring Data JPA
我想测试FooRepository.lock()
是否有效,在有人调用lock()
之后,其他人调用它应该等待。
以下是我最好的尝试,它不起作用。 我相信原因是entityManger
和fooRepository
都参与了同一个事务。
如何从另一个事务中调用lock()
? 或者对悲观锁进行单元测试的任何建议? 谢谢!!
FooRepositoryTest:
package com.example.demo;
import java.util.UUID;
import javax.persistence.LockModeType;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.boot.test.autoconfigure.orm.jpa.TestEntityManager;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@DataJpaTest
public class FooRepositoryTest {
@Autowired
private TestEntityManager entityManager;
@Autowired
private FooRepository fooRepository;
@Test
public void lockTest() {
// given
Foo foo = new Foo();
foo.setName("foo-name");
UUID fooId = fooRepository.save(foo).getFooId();
entityManager.flush();
entityManager.clear();
// when
Foo savedFoo = fooRepository.findOne(fooId);
fooRepository.lock(savedFoo);
// then
// I want something like this to be lock wait,
// something to confirm the above fooRepository.lock() work
entityManager.getEntityManager().lock(savedFoo, LockModeType.PESSIMISTIC_WRITE);
}
}
Foo类:
package com.example.demo;
import java.util.UUID;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
@Entity
public class Foo {
@Id
@GeneratedValue
private UUID fooId;
private String name;
public UUID getFooId() {
return fooId;
}
public void setFooId(UUID fooId) {
this.fooId = fooId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
FooApplication 类:
package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class FooApplication {
public static void main(String[] args) {
SpringApplication.run(FooApplication.class, args);
}
}
类 FooRepository:
package com.example.demo;
import java.util.UUID;
import org.springframework.data.jpa.repository.JpaRepository;
public interface FooRepository extends JpaRepository<Foo, UUID>, FooRepositoryCustom {
}
类 FooRepositoryCustom:
package com.example.demo;
public interface FooRepositoryCustom {
public void lock(Foo foo);
}
FooRepositoryImpl 类:
package com.example.demo;
import javax.persistence.EntityManager;
import javax.persistence.LockModeType;
import org.springframework.beans.factory.annotation.Autowired;
public class FooRepositoryImpl implements FooRepositoryCustom {
@Autowired
private EntityManager entityManager;
@Override
public void lock(Foo foo) {
entityManager.lock(foo, LockModeType.PESSIMISTIC_WRITE);
}
}
你得到错误的单元测试。
您不会编写单元测试来执行某些 3rd 方框架实现的功能。 单元测试适用于您的单元!
换句话说:您不需要验证锁定是否按预期工作。 您的单位可以:
entityManager.lock(foo, LockModeType.PESSIMISTIC_WRITE);
所以你可以考虑在这里测试的唯一一件事:确保使用预期的参数调用实体管理器lock()
方法。
含义:验证您的代码确实使用了您认为应该使用的框架 - 但不要测试其他人的代码! 你看 - 当你的单元测试表明框架是错误的时你会怎么做......你不能改变它! (当然,你可以写一个错误报告然后)
免责声明:在某些特殊情况下,您可能会假设某些 3rd 方产品存在错误 - 那么编写单元测试来测试此假设可能非常有用。 这样您以后就可以针对该产品的新版本运行单元测试,以查看错误是否仍然存在。
使用集成测试测试悲观锁定处理很重要(我可以说是强制性的吗?),原因有两个:
在博客文章使用 SpringBoot 和 JPA 测试悲观锁定处理中,您可以:
🔔 Spring 框架仅用作示例。 您可以轻松地为每个其他框架调整测试。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.