[英]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.