症状
次のテストメソッドを実行
OrderRestCntrollerTest.java
package com.example.restapi.order;
import com.example.restapi.domain.cartItem.CartItemService;
import com.example.restapi.domain.customer.CustomerService;
import com.example.restapi.domain.order.OrderService;
import com.example.restapi.implement.cartItem.CartItemDto;
import com.example.restapi.implement.order.OrderDto;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
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.web.servlet.MockMvc;
import org.springframework.test.web.servlet.ResultActions;
import javax.servlet.http.HttpServletRequest;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
@WebMvcTest
public class OrderRestControllerTest {
@Autowired
private MockMvc mockMvc;
@MockBean
private CustomerService customerService;
@MockBean
private OrderService orderService;
@MockBean
private CartItemService cartItemService;
@Test
@DisplayName("HttpResponseを引数とし、Createを実行したとき、注文情報がJson形式で返される。")
public void givenHttpResponse_whenCreate_thenReturnOrderbyJson() throws Exception {
// given-precondition or Setup
// make mock in customerId from HttpResponse
//HttpResponse -> Jwt -> customerId(Email)
HttpServletRequest request = null;
Integer customerId = Mockito.doReturn(3).when(customerService.getIdfromJwtToken(request));
// make mock in cartItem
List<CartItemDto> cartItemDtos = new ArrayList<>();
cartItemDtos.add(new CartItemDto(1,3,3,5));
cartItemDtos.add(new CartItemDto(1,3,7,1));
cartItemDtos.add(new CartItemDto(1,3,10,9));
cartItemDtos.add(new CartItemDto(1,3,13,9));
cartItemDtos.add(new CartItemDto(1,3,15,3));
Mockito.doReturn(cartItemDtos).when(cartItemService.listCartItems(customerId));
// make mock in Order create
OrderDto expectedOrderDto = new OrderDto(10,3,toDate(LocalDateTime.now()),3900f,300f,4200f,390f,4590f, "pending");
//when - action or the behavior that we are going test
ResultActions response = mockMvc.perform(get("/api/product",request));
//
// //then - verify the output
// response.andExpect(status().isOk())
// .andDo(print());
}
private Date toDate(LocalDateTime localDateTime) {
ZoneId zone = ZoneId.systemDefault();
ZonedDateTime zonedDateTime = ZonedDateTime.of(localDateTime, zone);
Instant instant = zonedDateTime.toInstant();
return Date.from(instant);
}
}
実行結果
error.txt(一部抜粋)
java.lang.IllegalStateException: Failed to load ApplicationContext
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'customerRestController': Unsatisfied dependency expressed through field 'authenticationManager'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.springframework.security.authentication.AuthenticationManager' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
違うドメインのエラーがでるのかが違和感があると思いした。
今実装しているドメインがorderなのに、customerRestControllerでエラーが出るのが変です。
原因
@WebMvcTestの引数が不足しているのが原因
引数無しで@webMvcTestを指定すると 全て の@RestControllerのアノテーションを参照する。
私は今までコントローラーの単体テストを書いていなく、それを突っ込まれたようです。
原因となるドメインの@RestControllerを片っ端からコメントアウトすると、症状は解消することで確認
対策
@WebMvcTestでテストしたいドメインのコントローラーを指定する。
WebMvcAnnotation.java
// 引数なしだとすべての@RestControllerを拾ってしまう。
@WebMvcTest
// 引数ありだと引数だけのクラスの@RestControllerを参照する。
@WebMvcTest(OrderRestController.class)
感想
私の様にコントローラの単体テストを後回しにしていたら直面するエラーだと思います。
よく直面するDIコンテナに値入ってない問題とは別のものなので 盲点でした。
参考