java - 通过 Spring Boot 测试运行时控制器中未发生 Bean 注入
问题描述
我创建了一个带有基于 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 时无法正常启动。我需要帮助。提前致谢。
解决方案
不要classes
为 @SpringBootTest 注解指定参数。
按照以下方式使用它
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
将导致 Spring Boot 在当前包中查找配置类,然后是父包等。最终找到您的SpringbootSecurityMysqlApplication
. 这将测试包括所有层在内的完整应用程序。
如果您想使用模拟服务单独测试控制器
@WebMvcTest(CalorieController.class)
并为您的测试中的服务提供模拟 bean
@MockBean
private LoleService lolService;
推荐阅读
- oracle - 什么是 Sqlite 中的等效 oracle 查询 trunc(date)?
- object - 将 1 个对象的值映射到其他对象的键
- nginx - NGINX 返回 301 而不是 404
- docker - docker-compose之后的网络与定义的名称不同?
- javascript - 所有对象的 Javascript 警报
- pandas - 名称“_Unspecified”未定义
- javascript - javascript:将对象添加到数组会更改对象属性
- mql5 - 我该如何解决这个问题:“'Price.mqh' (57,12) 中的数组超出范围”?
- python - 如何按字母顺序返回文本文件中的所有单词(每个单词一次)?
- ruby-on-rails - 如何使用正则表达式从日期字符串中提取日期