如何解决Spring boot Junit Test ResttemplateBuilder 构建方法给出空点异常
我试图从下面的服务类中覆盖断路器回退方法
@Component
public class UserService {
private static final String UNABLE_TO_CONNECT_TO_USER_SERVICE ="User service not available";
@Value("${user.service.url}")
private String baseUrl;
@Value("${user.service.username}")
private String userName;
@Value("${user.service.password}")
private String password;
public UserService(
RestTemplateBuilder restTemplateBuilder,@Qualifier("userService_client_factory")
HttpComponentsClientHttpRequestFactory httpComponentsClientHttpRequestFactory) {
var template = restTemplateBuilder.build();
template.setRequestFactory(httpComponentsClientHttpRequestFactory);
this.restTemplate = template;
}
@CircuitBreaker(name = "userservice",fallbackMethod = "fallback")
@Loggable
public User getUser(String userId) {
try {
LOGGER.debug("calling getUser for userId {}",userId);
ResponseEntity<User> responseEntity =
restTemplate.exchange(
buildUrl("/v2/{user-id}/user",userId),HttpMethod.GET,new httpentity<>(buildHeaders()),new ParameterizedTypeReference<User>() {});
return responseEntity.getBody();
} catch (HttpServerErrorException | ResourceAccessException e) {
throw new ServiceInvokeException(UNABLE_TO_CONNECT_TO_USER_SERVICE,e);
} catch (RestClientException e) {
throw new UserException(e.getMessage(),"Get User Failed");
}
}
@SuppressWarnings("all")
private User fallback(String userId,ServiceInvokeException e) {
throw new ServiceInvokeException(
format(UNABLE_TO_CONNECT_TO_USER_SERVICE,e.getMessage()),e);
}
private HttpHeaders buildHeaders() {
var headers = new HttpHeaders();
headers.setAccept(singletonList(APPLICATION_JSON));
headers.setContentType(APPLICATION_JSON);
headers.setBasicAuth(userName,password);
return headers;
}
private URI buildUrl(String path,String userId) {
Map<String,String> pathParameters = new HashMap<>();
pathParameters.put("user-id",userId);
String urlPath = baseUrl + path;
return UriComponentsBuilder.fromUriString(urlPath)
.buildAndExpand(pathParameters)
.toUri();
}
}
下面是编写的Junit测试用例
@RunWith(springrunner.class)
@DirtiesContext
@ContextConfiguration(
classes = {CircuitBreakerAutoConfiguration.class,UserService.class})
public class UserServiceFallBackTest {
private static final String USER_NAME = "userName";
private static final String PASSWORD = "password";
private static final String USERNAME_VAL = "uname";
private static final String PWD_VAL = "pwd";
private static final String userId = "test-userId";
private static final String ERROR_MESSAGE = "error message";
@Autowired
UserService userService;
@Rule
public ExpectedException thrown = ExpectedException.none();
@TestConfiguration
static class TestConfig {
@Bean
RestTemplateBuilder restTemplateBuilder() {
RestTemplateBuilder restTemplateBuilder = mock(RestTemplateBuilder.class);
RestTemplate restTemplate = mock(RestTemplate.class);
ResponseEntity responseEntity = mock(ResponseEntity.class);
when(restTemplateBuilder.build()).thenReturn(restTemplate);
when(restTemplate.exchange(
any(URI.class),eq(HttpMethod.GET),any(httpentity.class),any(ParameterizedTypeReference.class)))
.thenThrow(new HttpServerErrorException(HttpStatus.BAD_GATEWAY));
return restTemplateBuilder;
}
@Bean(name = "userService_client_factory")
HttpComponentsClientHttpRequestFactory factory(){
HttpComponentsClientHttpRequestFactory factory = mock(HttpComponentsClientHttpRequestFactory.class);
return factory;
}
@Bean
UserService userService() {
return new UserService(restTemplateBuilder(),factory());
}
}
@Test
public void createFallbackWrapsExceptionAsServiceInvokeException() {
thrown.expect(ServiceInvokeException.class);
userService.getUser(userId);
}
@Test
public void createFallbackWrapsExceptionAsRestClientException() {
thrown.expect(UserException.class);
userService.getUser(userId);
}
}
测试用例在 UserService.java 类 var template = restTemplateBuilder.build();
这里 restTemplateBuilder.build() 给出空的 restTemaplate 对象
解决方法
模拟不会进入@Bean 配置。 @Bean 方法生成 bean,仅此而已,代码超出范围并在此之后停止工作。
分离模拟
如果您希望在每次测试之前运行某些代码,也可以使用 @Before
;如果希望某些代码在所有测试之前运行一次,则可以使用 @BeforeAll
。
public class UserServiceFallBackTest {
private static final String USER_NAME = "userName";
private static final String PASSWORD = "password";
private static final String USERNAME_VAL = "uname";
private static final String PWD_VAL = "pwd";
private static final String userId = "test-userId";
private static final String ERROR_MESSAGE = "error message";
@Autowired
UserService userService;
@Rule
public ExpectedException thrown = ExpectedException.none();
@Mock
private RestTemplateBuilder restTemplateBuilder;
@Mock
private RestTemplate restTemplate;
@Mock
private ResponseEntity responseEntity;
@Before
private void init() {
when(restTemplateBuilder.build()).thenReturn(restTemplate);
when(restTemplate.exchange(
any(URI.class),eq(HttpMethod.GET),any(HttpEntity.class),any(ParameterizedTypeReference.class)))
.thenThrow(new HttpServerErrorException(HttpStatus.BAD_GATEWAY));
return restTemplateBuilder;
}
@TestConfiguration
static class TestConfig {
@Bean(name = "userService_client_factory")
HttpComponentsClientHttpRequestFactory factory(){
HttpComponentsClientHttpRequestFactory factory = mock(HttpComponentsClientHttpRequestFactory.class);
return factory;
}
@Bean
UserService userService() {
return new UserService(restTemplateBuilder(),factory());
}
}
@Test
public void createFallbackWrapsExceptionAsServiceInvokeException() {
thrown.expect(ServiceInvokeException.class);
userService.getUser(userId);
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。