Инъекция боба не происходит в контроллере при запуске через тест весенней загрузки - PullRequest
0 голосов
/ 19 декабря 2018

Я создал весеннее загрузочное веб-приложение с API на основе Rest.В моем контроллере есть служба, которая автоматически подключается и внедряется при нормальном запуске приложения при запуске через основное приложение.Однако, если я запустил свой интеграционный тест для этого контроллера.Я получаю следующее исключение.

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
    }

И это мой интеграционный тест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();
    }

}

Я не понимаю, почему тестовый класс не запускается должным образом с правильной инъекцией bean-компонентов. Мне нужна помощь в этом.Заранее спасибо.

1 Ответ

0 голосов
/ 19 декабря 2018

Не указывайте параметр classes для аннотации @SpringBootTest.

Использование его следующим образом

 @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)

заставит Spring Boot искать класс конфигурации в текущем пакете,затем родительский пакет и т. д. в конце концов найдет ваш SpringbootSecurityMysqlApplication.Это будет тестировать полное приложение, включая все слои.

Если вы хотите протестировать контроллер изолированно с помощью фиктивного сервиса, используйте

@WebMvcTest(CalorieController.class)

и предоставьте фиктивный компонент для сервиса в вашем тесте

@MockBean
private LoleService lolService;
...