删除集成测试中创建 bean 的异常,它不会出现在标准应用程序启动时
Remove exception with bean creation on integration test, which does not appear on standard application start
我有 spring 运行良好的启动应用程序,但是当我开始进行集成测试时,我发现项目中存在循环依赖:
@Service
public class CrowdManagerSyncService {
private final CrowdManagerSyncScheduler crowdManagerSyncScheduler;
@Autowired
public CrowdManagerSyncService(CrowdManagerSyncScheduler crowdManagerSyncScheduler) {
this.crowdManagerSyncScheduler = Objects.requireNonNull(crowdManagerSyncScheduler);
}
}
和
@Component
public class CrowdManagerSyncScheduler {
@Autowired
private CrowdManagerSyncService crowdManagerSyncService;
}
这不是我的代码,我现在还没准备好重写它。但它在生产中运行得非常好。在我的集成测试中
@RunWith(SpringRunner.class)
@WebMvcTest(UserController.class)
@WithMockUser(roles={"ADMIN"})
@ContextConfiguration(classes = {AdminConsoleApplication.class, DataSourceAutoConfiguration.class,
MockMvcAutoConfiguration.class, MockMvcWebDriverAutoConfiguration.class})
public class UserControllerTest {
@Autowired
private MockMvcHtmlUnitDriverBuilder builder;
private WebDriver webDriver;
@Before
public void setUp() throws Exception {
webDriver = builder.build();
}
}
我发现异常:
Error creating bean with name 'crowdManagerSyncService': Requested bean is currently in creation: Is there an unresolvable circular reference?
所以,我的问题是:如何在不消除可怕的循环依赖的情况下在测试中忽略这个问题?它在生产中运行良好,所以很确定有一些方法可以在不更改代码的情况下启动测试上下文。
@WebMvcTest
不适合 "proper" 集成测试。
来自 the api docs:
Can be used when a test focuses only on Spring MVC components.
但是,您随后使用 @ContextConfiguration
实质上将整个应用程序添加到测试中。
删除 @ContextConfiguration
并改为将 @MockBean
CrowdManagerSyncService
自动连接到您的测试中。
这将创建 CrowdManagerSyncService
的模拟版本并将其注入测试应用程序上下文中的 UserController
。
@RunWith(SpringRunner.class)
@WebMvcTest(UserController.class)
@WithMockUser(roles={"ADMIN"})
public class UserControllerTest {
@Autowired
private MockMvcHtmlUnitDriverBuilder builder;
@MockBean
private CrowdManagerSyncService service;
private WebDriver webDriver;
@Before
public void setUp() throws Exception {
webDriver = builder.build();
}
@Test
public void shouldWork() {
when(service.doStuff())
.thenReturn("Hello"); // regular Mockito mocking
}
}
如果您只是想测试 UserController
并回避循环依赖问题,这是合适的,因为在任何地方都没有 "real" CrowdManagerSyncService
的实例化。
您还可以将 @WebMvcTest
和 @ContextConfiguration
替换为 @SpringBootTest
(它像生产一样引导应用程序)和 @AutoConfigureMockMvc
(它将真正的 HTTP 内容替换为MockMvc).
我有 spring 运行良好的启动应用程序,但是当我开始进行集成测试时,我发现项目中存在循环依赖:
@Service
public class CrowdManagerSyncService {
private final CrowdManagerSyncScheduler crowdManagerSyncScheduler;
@Autowired
public CrowdManagerSyncService(CrowdManagerSyncScheduler crowdManagerSyncScheduler) {
this.crowdManagerSyncScheduler = Objects.requireNonNull(crowdManagerSyncScheduler);
}
}
和
@Component
public class CrowdManagerSyncScheduler {
@Autowired
private CrowdManagerSyncService crowdManagerSyncService;
}
这不是我的代码,我现在还没准备好重写它。但它在生产中运行得非常好。在我的集成测试中
@RunWith(SpringRunner.class)
@WebMvcTest(UserController.class)
@WithMockUser(roles={"ADMIN"})
@ContextConfiguration(classes = {AdminConsoleApplication.class, DataSourceAutoConfiguration.class,
MockMvcAutoConfiguration.class, MockMvcWebDriverAutoConfiguration.class})
public class UserControllerTest {
@Autowired
private MockMvcHtmlUnitDriverBuilder builder;
private WebDriver webDriver;
@Before
public void setUp() throws Exception {
webDriver = builder.build();
}
}
我发现异常:
Error creating bean with name 'crowdManagerSyncService': Requested bean is currently in creation: Is there an unresolvable circular reference?
所以,我的问题是:如何在不消除可怕的循环依赖的情况下在测试中忽略这个问题?它在生产中运行良好,所以很确定有一些方法可以在不更改代码的情况下启动测试上下文。
@WebMvcTest
不适合 "proper" 集成测试。
来自 the api docs:
Can be used when a test focuses only on Spring MVC components.
但是,您随后使用 @ContextConfiguration
实质上将整个应用程序添加到测试中。
删除 @ContextConfiguration
并改为将 @MockBean
CrowdManagerSyncService
自动连接到您的测试中。
这将创建 CrowdManagerSyncService
的模拟版本并将其注入测试应用程序上下文中的 UserController
。
@RunWith(SpringRunner.class)
@WebMvcTest(UserController.class)
@WithMockUser(roles={"ADMIN"})
public class UserControllerTest {
@Autowired
private MockMvcHtmlUnitDriverBuilder builder;
@MockBean
private CrowdManagerSyncService service;
private WebDriver webDriver;
@Before
public void setUp() throws Exception {
webDriver = builder.build();
}
@Test
public void shouldWork() {
when(service.doStuff())
.thenReturn("Hello"); // regular Mockito mocking
}
}
如果您只是想测试 UserController
并回避循环依赖问题,这是合适的,因为在任何地方都没有 "real" CrowdManagerSyncService
的实例化。
您还可以将 @WebMvcTest
和 @ContextConfiguration
替换为 @SpringBootTest
(它像生产一样引导应用程序)和 @AutoConfigureMockMvc
(它将真正的 HTTP 内容替换为MockMvc).