programing

SpringBoot 1.4에서 SpringMVC 슬라이스 테스트 문제

batch 2023. 6. 20. 21:28
반응형

SpringBoot 1.4에서 SpringMVC 슬라이스 테스트 문제

새로운 Spring Boot 1.4 MVC 테스트 기능을 사용해보고 있습니다.저는 다음과 같은 컨트롤러를 가지고 있습니다.

@Controller
public class ProductController {

  private ProductService productService;

  @Autowired
  public void setProductService(ProductService productService) {
    this.productService = productService;
  }

  @RequestMapping(value = "/products", method = RequestMethod.GET)
  public String list(Model model){
    model.addAttribute("products", productService.listAllProducts());
     return "products";
  }
}

최소한의 제품 서비스 구현은 다음과 같습니다.

@Service
public class ProductServiceImpl implements ProductService {
  private ProductRepository productRepository;

  @Autowired
  public void setProductRepository(ProductRepository productRepository) {
    this.productRepository = productRepository;
  }

  @Override
  public Iterable<Product> listAllProducts() {
    return productRepository.findAll();
  }

}

제품 리포지토리의 코드는 다음과 같습니다.

public interface ProductRepository extends CrudRepository<Product,    
 Integer>{
}

새로운 @WebMvcTest를 사용하여 컨트롤러를 테스트하려고 합니다.저의 견해는 타임리프 팀 플레이트입니다.컨트롤러 테스트는 다음과 같습니다.

@RunWith(SpringRunner.class)
@WebMvcTest(ProductController.class)

public class ProductControllerTest {
private MockMvc mockMvc;

@Before
public void setUp() {
    ProductController productController= new ProductController();       
    mockMvc = MockMvcBuilders.standaloneSetup(productController).build();
}

@Test
public void testList() throws Exception {        
mockMvc.perform(MockMvcRequestBuilders.get("/products"))                 
.andExpect(MockMvcResultMatchers.status().isOk())                
.andExpect(MockMvcResultMatchers.view().name("products"))             
 .andExpect(MockMvcResultMatchers.model().attributeExists("products"));               
 }
}

하지만 테스트를 실행할 때 이 오류가 발생합니다.

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'productController': Unsatisfied dependency expressed through method 'setProductService' parameter 0: No qualifying bean of type [guru.springframework.services.ProductService] found for dependency [guru.springframework.services.ProductService]: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [guru.springframework.services.ProductService] found for dependency [guru.springframework.services.ProductService]: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}

제품 컨트롤러를 제대로 테스트하려면 문제를 해결하는 데 도움이 필요합니다.추가 제안 및 컨트롤러에 대한 보다 철저한 테스트를 위한 Expect() 제안은 높이 평가될 것입니다.

잘 부탁드립니다.

전체 응용 프로그램을 로드할 의향이 있는 사용자는 다음을 사용해 보십시오.@SpringBootTest와 결합하여@AutoConfigureMockMvc보다도@WebMvcTest.

저는 꽤 오랫동안 그 문제와 씨름해 왔지만, 마침내 완전한 그림을 얻었습니다.
제가 지금까지 찾은 공식 스프링 문서뿐만 아니라 인터넷에 있는 많은 튜토리얼은 다음을 사용하여 컨트롤러를 테스트할 수 있다고 명시하고 있습니다.@WebMvcTest그것은 전적으로 맞습니다, 여전히 이야기의 절반을 생략합니다.
이러한 주석의 자바독이 지적한 바와 같이, 이는 컨트롤러를 테스트하기 위한 것일 뿐이며 앱의 모든 빈을 로드하지는 않으며, 이는 설계상의 것입니다.
다음과 같은 명시적 빈 스캔 주석과도 호환되지 않습니다.@Componentscan.

저는 이 문제에 관심이 있는 사람이라면 누구나 주석의 전체 자바독(30줄 길이에 요약된 유용한 정보로 채워져 있음)을 읽을 것을 제안합니다. 하지만 저는 제 상황과 관련된 보석 몇 개를 추출할 것입니다.

주석 유형에서 WebMvcTest

이 주석을 사용하면 전체 자동 구성이 비활성화되고 대신 MVC 테스트와 관련된 구성만 적용됩니다(예:@Controller,@ControllerAdvice,@JsonComponent필터,WebMvcConfigurer그리고.HandlerMethodArgumentResolver콩이나 콩이@Component,@Service또는@Repository콩)[...] 전체 응용 프로그램 구성을 로드하고 MockMVC를 사용하려는 경우주석 대신 이 주석과 결합하는 것을 고려해야 합니다.

그리고 사실, 오직.@SpringBootTest+@AutoConfigureMockMvc내 문제를 고쳤고, 다른 모든 접근 방식을 사용했습니다.@WebMvcTest필요한 콩 일부를 로드하지 못했습니다.

편집

Spring 문서에 대해 언급한 내용을 취소합니다. 사용자가 다음을 사용할 때 한 조각이 암시되었음을 몰랐기 때문입니다.@WebMvcTest실제로 MVC 슬라이스 설명서는 슬라이스의 특성상 모든 앱이 로드되지 않는다는 점을 분명히 했습니다.

Spring Boot 1.4가 포함된 사용자 지정 테스트 슬라이스

테스트 슬라이싱은 테스트를 위해 만들어진 응용프로그램 컨텍스트를 분할하는 것입니다.일반적으로 MockMvc를 사용하여 컨트롤러를 테스트하려는 경우에는 데이터 계층에 문제가 발생하지 않도록 해야 합니다.대신 컨트롤러가 사용하는 서비스를 조롱하고 모든 웹 관련 상호 작용이 예상대로 작동하는지 확인할 수 있습니다.

은 사중입다니를 사용하고 .@WebMvcTest하는 MockMvc사례.그것은 주요 목적 중 하나로서 말이 안 됩니다.@WebMvcTest으로 으로구것다니입을 하는 것입니다.MockMvc당신을 위한 예.또한사중구성는서에수를 하고 있습니다.standaloneSetup즉, 컨트롤러에 종속성을 주입하는 것을 포함하여 테스트할 컨트롤러를 완전히 구성해야 합니다.당신은 그것을 하지 않고 있습니다 그것은 원인이 됩니다.NullPointerException.

당신이 경우용을 사용하고 .@WebMvcTest그리고 저는 당신이 그렇게 하는 것을 추천합니다, 당신은 당신의 것을 제거할 수 있습니다.setUp으로 구성된 "입니다.MockMvc 인턴스대사주입됨여를 하여 인스턴스를 합니다.@Autowired밭.밭.

를 하기 위해서, 기하해제어음.ProductService에의사용에 의해 됩니다.ProductController당신은 새로운 것을 사용할 수 있습니다.@MockBean 작성을 ProductService그런 다음 주입될 것입니다.ProductController.

이러한 변경 사항으로 인해 테스트 클래스는 다음과 같이 됩니다.

package guru.springframework.controllers;

import guru.springframework.services.ProductService;
import org.hamcrest.Matchers;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;

import static org.assertj.core.api.Assertions.assertThat;

@RunWith(SpringRunner.class)
@WebMvcTest(ProductController.class)
public class ProductControllerTest {

    @Autowired
    private MockMvc mockMvc;

    @MockBean
    private ProductService productService;

    @Test
    public void testList() throws Exception {
      mockMvc.perform(MockMvcRequestBuilders.get("/products"))
                .andExpect(MockMvcResultMatchers.status().isOk())
                 .andExpect(MockMvcResultMatchers.view().name("products"))
                 .andExpect(MockMvcResultMatchers.model().attributeExists("products"))
               .andExpect(MockMvcResultMatchers.model().attribute("products",
                        Matchers.is(Matchers.empty())));

    }
}

자동배선 MockMvc 대신 MockMvc 객체를 이렇게 설정 단계에서 인스턴스화했습니다.

protected void setUp() {
        mvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
    }

다음 장식을 추가했는데도 여전히 작동하지 않는 경우:

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;

@RunWith(SpringRunner.class)
@SpringBootTest
@AutoConfigureMockMvc
public class SomeTest {

    @Autowired
    private MockMvc mockMvc;


    @Test
    public void somePositiveTest() throws Exception {
        mockMvc.perform(MockMvcRequestBuilders.get(url))
                .andExpect(status().is2xxSuccessful());
    }
}

다음 종속성을 pom.xml에 추가했는지 확인합니다.

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

언급URL : https://stackoverflow.com/questions/38084872/issue-with-testing-spring-mvc-slice-in-springboot-1-4

반응형