在我的集成测试中,我想提前用@BeforeAll (见下文)在我的测试用例中可以依赖的数据填充我的系统。
package com.ksteindl.chemstore.service;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.annotation.Rollback;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import javax.transaction.Transactional;
//some other import of my own stuff
@ExtendWith(SpringExtension.class)
@ActiveProfiles("test")
@SpringBootTest(webEnvironment= SpringBootTest.WebEnvironment.RANDOM_PORT)
@AutoConfigureMockMvc
public class ShelfLifeServiceTest extends BaseControllerTest {
@Autowired
private ShelfLifeService shelfLifeService;
@Autowired
private ChemTypeService chemTypeService;
@BeforeAll
static void setUpTestDb(@Autowired ShelfLifeService shelfLifeService,@Autowired ChemTypeService chemTypeService) {
ShelfLifeInput input = LabAdminTestUtils.getSolidForAlphaInput();
Long chemTypeId = chemTypeService.getChemTypes().stream()
.filter(chemType -> chemType.getName().equals(LabAdminTestUtils.SOLID_COMPOUND_NAME))
.findAny()
.get()
.getId();
input.setChemTypeId(chemTypeId);
shelfLifeService.createShelfLife(input, AccountManagerTestUtils.BETA_LAB_MANAGER_PRINCIPAL);
}
@Test
@Rollback
@Transactional
public void testCreateShelfLife_whenAllValid_gotNoException() {
ShelfLifeInput input = LabAdminTestUtils.getSolidForBetaInput();
Long chemTypeId = chemTypeService.getChemTypes().stream()
.filter(chemType -> chemType.getName().equals(LabAdminTestUtils.SOLID_COMPOUND_NAME))
.findAny()
.get()
.getId();
input.setChemTypeId(chemTypeId);
shelfLifeService.createShelfLife(input, AccountManagerTestUtils.BETA_LAB_MANAGER_PRINCIPAL);
}
}我的问题是当我运行测试时,我从@BeforeAll方法抛出了一个LazyInicializtionException
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.ksteindl.chemstore.domain.entities.Lab.labManagers, could not initialize proxy - no Session
...
at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.base/java.util.stream.ReferencePipeline.anyMatch(ReferencePipeline.java:528)
at com.ksteindl.chemstore.service.ShelfLifeService.getAndValidateLab(ShelfLifeService.java:92)
at com.ksteindl.chemstore.service.ShelfLifeService.createOrUpdateShelfLife(ShelfLifeService.java:65)
at com.ksteindl.chemstore.service.ShelfLifeService.createShelfLife(ShelfLifeService.java:47)
at com.ksteindl.chemstore.service.ShelfLifeServiceTest.setUpTestDb(ShelfLifeServiceTest.java:39)有趣的是,当我注释掉@BeforeAll方法时,我的测试运行正常,没有任何异常。正如您所看到的,这两个方法的内容几乎相同(只是输入不同,以防止彼此冲突)。抛出异常的确切代码如下所示:
private Lab getAndValidateLab(String labKey, Principal principal) {
Lab lab = labService.findLabByKey(labKey);
lab.getLabManagers().stream().filter(/*some predicate*/).findAny().orElseThrow(/*throw validation Exception*/);
return lab;
}这是真的,Lab和labManagers属性之间的关系是惰性的,但是我不能理解为什么Spring不像在testCreateShelfLife_whenAllValid_gotNoException中那样在一个事务中获得这些数据。当然,ShelfLifeService.createShelfLife()在Rest控制器调用中工作得非常好。谢谢你的帮助!实体:
@Entity
@Data
public class Lab {
//...
@ManyToMany(fetch = FetchType.LAZY)
@JoinTable(name = "MANAGER_OF_LAB_TABLE", joinColumns = @JoinColumn(name = "LAB_ID"), inverseJoinColumns = @JoinColumn(name = "APP_USER_ID"))
@JsonIgnore
private List<AppUser> labManagers;
}
@Entity
@Data
public class AppUser {
//...
@ManyToMany(mappedBy = "labManagers")
private List<Lab> managedLabs;
}发布于 2021-09-16 14:19:27
将@BeforeAll (在初始化Spring容器之前运行)更改为@BeforeEach (将在每次测试之前运行,在Spring容器初始化之后运行),但在构建测试和Spring容器之后运行。
我认为在Spring容器完全构建之前,chemTypeService已经在@BeforeAll中执行了。-有点猜测
在每次测试之前,也可以查看@DirtiesContext来重新构建Spring上下文。
查看此tutorial
另一个有点老套的解决方案是在spring容器初始化后创建自己的类来加载测试数据:
@Service
@Profile("test")
public class TestInit {
@Autowired
private ShelfLifeService shelfLifeService;
@Autowired
private ChemTypeService chemTypeService;
@PostConstruct
private void init() {
ShelfLifeInput input = LabAdminTestUtils.getSolidForAlphaInput();
Long chemTypeId = chemTypeService.getChemTypes().stream()
.filter(chemType -> chemType.getName().equals(LabAdminTestUtils.SOLID_COMPOUND_NAME))
.findAny()
.get()
.getId();
input.setChemTypeId(chemTypeId);
shelfLifeService.createShelfLife(input, AccountManagerTestUtils.BETA_LAB_MANAGER_PRINCIPAL);
}
}https://stackoverflow.com/questions/69209673
复制相似问题