我有一个@RestController
,它在@Autowire
字段中只有一个依赖项,该依赖项是@component,该组件的类定义有一些自动连接的字段,这些字段是@service,这些服务有一些@ repository。
在整个流程中,我使用了Kafka、Quartz、Cassandra和DB2。因此,当我为控制器创建单元测试用例时,我不想设置整个应用程序。因此,我决定使用@webMvcTest,并在控制器类的唯一依赖项上使用@MockBean。
但是我的测试抛出了异常,因为它试图创建一个标记为@repository的Dao bean。
@ActiveProfiles("test")
@WebMvcTest(controllers = MyControllerTest .class)
class MyControllerTest {
@MockBean
MyControllerDependency dependency;
@Autowired
MockMvc mockMvc;
@Test
void test_something() throws Exception {
assert(true);
}
}
下面是代码的简化版本
@Component
class MyControllerDependency {
@AutoiWired
MyCustomService service;
}
@Service
class MyCustomService{
@Autowired
MyCustomDao dao;
}
@Repository
class MyCustomDao{
@Autowired
private JdbcTemplate template;
}
我在测试中得到以下异常。
Exception
***************************
APPLICATION FAILED TO START
***************************
Description:
Field template in com.....MyCustomDao` required a bean of type 'org.springframework.jdbc.core.JdbcTemplate' that could not be found.
问题是,当我使用@WebMvcTest
slice并且已经模拟了唯一需要的依赖项MyControllerDependency
时,为什么spring test context试图加载MyCustomDao
,它被注解为@Repository
。
我可以用SpringbootTest
和AutoconfigureMockMVC
进行集成测试,但是为了编写控制器的Junit测试,我需要使用WebMvcTest
slice。
4条答案
按热度按时间0vvn1miw1#
我遇到了一个类似的问题,我想使用@WebMvcTest只测试我的控制器,但是spring上下文试图创建不依赖的spring bean,并且失败了,如下所示。
无法加载ApplicationContext java.lang。IllegalStateException:无法加载应用程序上下文,原因是:未满足的依赖项异常:创建文件中定义的名为“TestController”的Bean时出错...
解决方案:对于像
@ContextConfiguration(classes = DemoController.class)
这样的例子,只加载控制器。qf9go6mv2#
您的
@SpringBootApplication
上是否有任何活动的@ComponentScan("...")
注解?如Sping Boot 参考文档中所述:
另一个混淆的来源是类路径扫描。假设,当你以一种合理的方式组织代码时,你需要扫描一个额外的包。你的应用程序可能类似于以下代码:
这样做有效地覆盖了默认的组件扫描指令,其副作用是扫描这两个包,而不管您选择的切片。例如,@DataJpaTest似乎突然扫描了应用程序的组件和用户配置。同样,将自定义指令移动到单独的类是解决此问题的好方法。
一个解决方案是创建一个单独的
@Configuration
,并使用@ComponentScan
进行注解。当创建@WebMvcTest
时,配置(及其组件扫描被忽略)。rsl1atfo3#
当你在spring Boot main application class上有显式的@ComponentScan annotation时,通常会发生这种情况。
@ComponentScan注解抑制了@Webmvctest的默认组件扫描机制,它向上扫描包层次结构并应用excludeFilters仅查找控制器及其相关类。
3htmauhk4#
当你使用
@MockBean
注解来模拟你的bean时,你应该定义当你调用它的方法时被模拟的bean应该做什么,你通常在Mockito中使用when
来做这件事。在你的例子中,可以这样做:在此行:
当你发送一个
GET
请求到/api/test/restpoint
路径时,你应该把你的控制器调用的MyControllerDependency
类的任何方法都放在dependency.sample()
上,而不是dependency.sample()
,并且用thenReturn("Hello, Mock")
定义那个方法的模拟输出(当它在单元测试中被你的控制器调用时)。