在Spring Boot中禁用用于在TeamCity中构建的数据库自动配置

时间:2017-02-17 06:00:57

标签: spring spring-boot

我需要在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;

}

1 个答案:

答案 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;

}