通过Spring Boot Test

时间:2018-12-19 20:31:30

标签: java spring spring-boot testing spring-boot-test

我已经使用基于Rest的api创建了spring boot Web应用程序。 我的控制器具有一项服务,当通过主应用程序运行该应用程序正常启动时,该服务会自动连线并注入。但是,如果我为该控制器运行集成测试。我收到以下异常。

Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: 
No qualifying bean of type 'com.xyz.test.service.LolService' available: expected
 at least 1 bean which qualifies as autowire candidate. Dependency annotations: 
{@org.springframework.beans.factory.annotation.Autowired(required=true)}

这是我的控制器类。

package com.xyz.test.controller;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;

import lombok.extern.slf4j.Slf4j;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.xyz.test.model.Lol;
import com.xyz.test.service.LolProcessingService;
import com.xyz.test.service.LolService;


@RestController
@RequestMapping("/api")
@Slf4j
public class CalorieController {

    @Autowired
    private LoleService lolService;

    @Autowired
    private LolProcessingService lolProcessingService;


    @PostMapping("/lol")
    @PreAuthorize("hasRole('USER')")
    public FoodIntake createLol( @Valid @RequestBody Lol lol) throws Exception {
        return lolProcessingService.processNewLol(lol);
    }
}

这是我的服务课程

package com.xyz.test.service.impl;
   @Service
    public class LolServiceImpl implements LolService{

        @Autowired
        private LolRepository lolRepository;

    //some methods
    }

这是我的集成测试课程。

package com.xyz.test.rest;

import org.json.JSONException;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.skyscreamer.jsonassert.JSONAssert;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.boot.web.server.LocalServerPort;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.test.context.junit4.SpringRunner;

import com.xyz.test.controller.CalorieController;


@RunWith(SpringRunner.class)
@SpringBootTest(classes = CalorieController.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@EnableAutoConfiguration
@ComponentScan
public class LolControllerTest {


    @LocalServerPort
    private int port;

    TestRestTemplate restTemplate = new TestRestTemplate();

    HttpHeaders headers = new HttpHeaders();


    @Test
    public void testabc() throws JSONException {
        headers.add("Authorization","Basic cGFtcGxlOnBhbXBsZTEyMw==");
        HttpEntity<String> entity = new HttpEntity<String>(null, headers);

        ResponseEntity<String> response = restTemplate.exchange(
                createURLWithPort("/api/lol/pample"),
                HttpMethod.GET, entity, String.class);

        String expected = "[]";

        JSONAssert.assertEquals(expected, response.getBody(), false);
    }

    private String createURLWithPort(String uri) {
        return "http://localhost:" + port + uri;
    }


}

最后这是主要应用程序

package com.xyz.test;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
import org.springframework.web.client.RestTemplate;

@SpringBootApplication
@EnableJpaAuditing
public class SpringbootSecurityMysqlApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringbootSecurityMysqlApplication.class, args);
    }

    //bean for making http external calls
    @Bean 
    RestTemplate restTemplate() {
        return new RestTemplate();
    }

}

我不明白为什么在正确注入bean的情况下测试类无法正常启动。预先感谢。

1 个答案:

答案 0 :(得分:2)

不要为@SpringBootTest批注指定classes参数。

以下列方式使用

 @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)

将导致Spring Boot在当前包中查找配置类,然后在父包中查找。最终找到您的SpringbootSecurityMysqlApplication。这将测试包括所有层在内的完整应用程序。

如果要通过模拟服务使用隔离测试控制器

@WebMvcTest(CalorieController.class)

并在测试中为服务提供模拟bean

@MockBean
private LoleService lolService;