当 运行 通过 spring 引导测试时,Bean 注入不会在控制器中发生

Bean Injection not happening in controller when run via spring boot Test

我已经使用基于 Rest 的 api 创建了一个 spring 引导 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)}

这是我的控制器class。

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);
    }
}

这是我的服务class

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

        @Autowired
        private LolRepository lolRepository;

    //some methods
    }

这是我的集成测试 class。

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();
    }

}

我不明白为什么测试 class 不能通过正确注入 bean 正常启动。我需要这方面的帮助。提前致谢。

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

使用方法如下

 @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)

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

如果您想单独测试控制器与模拟服务使用

@WebMvcTest(CalorieController.class)

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

@MockBean
private LoleService lolService;