我需要在TeamCity构建中执行的测试阶段禁用数据库自动配置。
我在这里红了很多Q / A但是没有一个能为我工作。我(想)已禁用所有自动配置指令。
这是我的测试类,不能使用数据库(服务层被模拟):
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {TestContext.class, WebAppContext.class})
@SpringBootTest(classes = ApplicationTest.class)
public class EnvelopeControllerTest {
}
和TestContext.class
:
@Configuration
@ComponentScan("com.example")
@EnableWebMvc
@Profile("test")
public class TestContext {
@Bean
public EnvelopeService envelopeService() {
return Mockito.mock(EnvelopeService.class);
}
@Bean
public UtilService utilService() {
return Mockito.mock(UtilService.class);
}
}
和ApplicationTest.class
类
@SpringBootApplication
@EnableAutoConfiguration(exclude = {DataSourceAutoConfiguration.class, DataSourceTransactionManagerAutoConfiguration.class, HibernateJpaAutoConfiguration.class})
@ActiveProfiles("test")
public class ApplicationTest extends SpringBootServletInitializer {
private static Logger LOG = LogManager.getLogger(ApplicationTest.class);
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(ApplicationTest.class);
}
public static void main(String[] args) throws Exception {
SpringApplication application = new SpringApplication(ApplicationTest.class);
application.setBannerMode(Banner.Mode.OFF);
application.run(args);
}
}
并创建了空application-test.properties
个文件,该文件不包含连接到DB的信息,因此不应处理恕我直言的自动配置。
但是当我在TeamCity中运行build时,应用程序仍在尝试连接数据库。
我做错了什么?
关于Kamill Sokol的回答更新#1 。
我无法实现您的建议,现在我将控制器类最小化如下:
@RunWith(SpringRunner.class)
@WebMvcTest(EnvelopeController.class)
public class EnvelopeControllerTest {
@Test
public void failingTest() {
fail("Something goes wrong");
}
}
但现在测试无法运行,因为EnvelopeController
无法实例化 - 没有可用的bean依赖项。在我的解决方案中,我有一个TestContext
来初始化这些bean。如何用你的建议解决这个问题?
引起: org.springframework.beans.factory.UnsatisfiedDependencyException: 创建名称为' envelopeController的bean时出错':不满意 通过方法' setUtilService'表达的依赖关系参数0; 嵌套异常是 org.springframework.beans.factory.NoSuchBeanDefinitionException:没有 属于' com.example.api.services.UtilService'的限定bean 可用:预计至少有1个符合autowire资格的bean 候选人。依赖注释:{}
在我能够运行测试类之后,我需要实现这样的测试:
@Test
public void findById() throws Exception {
final String uuidString = "6c2b1c8a-3c29-4160-98b0-b8eaea7ea4d1";
final UUID id = UUID.fromString(uuidString);
final Envelope envelope = createEnvelope(id);
when(envelopeService.findOne(id, currentUser)).thenReturn(Optional.of(envelope));
when(utilService.getLoggedInUser()).thenReturn(currentUser);
mockMvc.perform(get("/api/envelopes/{id}", uuidString))
.andExpect(status().isOk())
.andExpect(content().contentType(Util.APPLICATION_JSON_UTF8))
.andExpect(jsonPath("$..id").value(uuidString));
verify(envelopeService, times(1)).findOne(id, currentUser);
}
它会与您的解决方案一起使用吗?
更新#2
当我包含示例中的所有模拟bean时会发生此错误:
引起: org.springframework.beans.factory.UnsatisfiedDependencyException: 创建名称为' envelopeController的bean时出错':不满意 通过方法' setEnvelopeRepository'表达的依赖关系参数 0;嵌套异常是 org.springframework.beans.factory.BeanCreationException:错误 使用name' envelopeRepository'创建bean:无法创建内部bean '(内豆)#1229a2b7'类型 [org.springframework.orm.jpa.SharedEntityManagerCreator]设置时 bean property' entityManager&#39 ;;嵌套异常是 org.springframework.beans.factory.BeanCreationException:错误 创建名称为'(内部bean)的bean#1229a2b7':无法解析 引用bean' entityManagerFactory'在设置构造函数时 参数;嵌套异常是 org.springframework.beans.factory.NoSuchBeanDefinitionException:没有 bean命名为'entityManagerFactory'可用
在玩了一些之后,似乎我需要@MockBean
所有这个控制器使用的所有bean所必需的bean,这是真的吗?这不方便。当我有TestContext
类时,我在这个上下文类中有mock-beans,我不需要为所有测试控制器类手动创建。谢谢你的帮助。
更新#3 - EnvelopeController
类依赖关系:
@RestController
@RequestMapping(APIController.API_ROOT + "/envelopes")
public class EnvelopeController extends APIController {
private EnvelopeService envelopeService;
private DateService dateService;
@Autowired
public void setEnvelopeService(EnvelopeService envelopeService) {
Assert.notNull(envelopeService);
this.envelopeService = envelopeService;
}
@Autowired
public void setDateService(DateService dateService) {
Assert.notNull(dateService);
this.dateService = dateService;
}
// REST API endpoints are omitted
}
和EnvelopeService类:
public class DefaultEnvelopeService implements EnvelopeService {
private EnvelopeRepository envelopeRepository;
private BalanceService balanceService;
private ScheduleService scheduleService;
}
答案 0 :(得分:0)
尽管您有@SpringBootTest(classes = ApplicationTest.class)
课程,但您仍然使用ApplicationTest
引导整个应用程序上下文。
将其更改为@SpringBootTest(classes = EnvelopeController.class)
。您的测试中不需要专用的ApplicationTest
。
根本原因
@SpringBootTest(classes = ApplicationTest.class)
所在的 ApplicationTest
scans the classpath。因为你的类路径上有一个没有Application
的相应exclude = {DataSourceAutoConfiguration.class, HibernateJpaAutoConfiguration.class}
类,所以在这种情况下Spring引导数据库。
测试Spring Boot 1.4中的改进
Spring Boot 1.4 introduced测试切片和Mockito的特殊注释。现在,您可以将测试简化为:
@RunWith(SpringRunner.class)
@WebMvcTest(EnvelopeController.class)
public class EnvelopeControllerTest {
@Autowired
private MockMvc mockMvc;
@MockBean
private EnvelopeService envelopeService;
@MockBean
private UtilService utilService;
}