I want to test a Tasklet implementation which uses an #Autowired RestTemplateBuilder to build a RestTemplate. The RestTemplate executes a request. I want to mock the response of this request.
#ContextConfiguration(classes = DogTasklet.class )
#RunWith(SpringRunner.class)
public class DogTaskletTest {
#MockBean
RestTemplateBuilder restTemplateBuilder;
private RestTemplate restTemplate = new RestTemplate();
#Autowired
private Tasklet sut;
#Before
public void setUp() throws Exception {
given(this.restTemplateBuilder.build()).willReturn(restTemplate);
}
}
The given() statement throws a NPE because the RestTemplateBuilder instance is null. What have I missed?
Update: I changed the test to the following which solves the NPE, now I have null ResponseEntity during sut.execute().
#RunWith(SpringRunner.class)
public class DogTaskletTest {
#TestConfiguration
static class TestConfig {
#Bean
RestTemplateBuilder restTemplateBuilder() {
RestTemplateBuilder restTemplateBuilder = mock(RestTemplateBuilder.class);
RestTemplate restTemplate = mock(RestTemplate.class);
ResponseEntity responseEntity = mock(ResponseEntity.class);
given(restTemplateBuilder.build()).willReturn(restTemplate);
given(restTemplate.execute(any(), any(), any(), any())).willReturn(responseEntity);
given(responseEntity.getBody()).willReturn("{}");
return restTemplateBuilder;
}
#Bean
DogTasklet sut() {
return new DogTasklet("string", restTemplateBuilder());
}
}
#Test
public void execute() throws Exception {
// when
sut.execute(stepContribution, chunkContext);
}
}
Thanks to Urosh I figured out that I was mocking the wrong method in my given() statement. Therefore it did not return the mocked RestTemplate.
I changed the given() to:
given(restTemplate.exchange(
anyString(),
eq(HttpMethod.GET),
any(HttpEntity.class),
eq(String.class)
)).willReturn(responseEntity);
Related
I have a Circuit breaker implemented which works fine when I run it (meaning the fallback method is run whenever the RestTemplate receives an HTTP status code between 400 and 599). However, when I try to unit test this fallback, by returning a Bad Request (HTTP 400) the fallback method is not invoked. Why is this?
Snippet from class:
class Test {
#Autowired
private RestTemplate restTemplate;
#HystrixCommand(fallbackMethod = "fallback")
public void test() {
HttpEntity<Object> testRequest = new HttpEntity<>();
ResponseEntity<String> response = restTemplate.exchange(
"http://localhost:8080/testurl",
HttpMethod.POST,
testRequest,
String.class);
}
private void fallback() {
System.out.println("Fallback method called");
}
}
Snippet from test class
#MockBean
private RestTemplate mockRestTemplate;
#Autowired
Test test;
#Test
public void testRestTemplateReturning400() {
ResponseEntity<String> response = new ResponseEntity<>(HttpStatus.BAD_REQUEST);
when(mockRestTemplate.exchange(anyString(), any(), any(), eq(String.class))).thenReturn(response);
test.test();
verify(mockRestTemplate, times(1)).exchange(anyString(), any(), any(), eq(String.class));
}
Add
#EnableCircuitBreaker
#EnableAspectJAutoProxy
to your test configuration
I am trying to write a unit test for spring controller, the myService class is autowired in myController,I have mocked myService class but when I debug the code it is coming null
myService = null
I am not able to inject this service for my controller.
#RunWith(MockitoJUnitRunner.class)
public class TestManageDevices {
private MockMvc mockMvc;
#Mock
MyService myService;
#Before
public void setUp() {
mockMvc = MockMvcBuilders.standaloneSetup(new MyController())
.build();
}
#Test
public void shouldPass() throws Exception {
Mockito.doNothing().when(myService).someMethod(Mockito.anyString(), Mockito.anyString(), Mockito.anyString());
JobResponse jobResponse = JobResponse.builder().responseCode(0).build();
jobResponse.requestObj = "mockedStringObject";
RequestBuilder requestBuilder = MockMvcRequestBuilders.post("/pathfortest")
.contentType(MediaType.APPLICATION_JSON_UTF8)
.param("id", Mockito.anyString());
MvcResult result = mockMvc.perform(requestBuilder).andReturn();
System.out.println(result.getResponse().getContentAsString());
MockHttpServletResponse response = result.getResponse();
Assert.assertEquals(HttpStatus.CREATED.value(), response.getStatus());
}
}
You are newing up the controller manually with new MyController() in the setUp method, so dependencies are not being injected.
Create a variable of type controller
#InjectMocks
MyController myController;
Use this when creating mockMVC instance in your setUp method as below:
mockMvc = MockMvcBuilders.standaloneSetup(myController).build();
This should work.
I am trying to mock RestTemplate but I when debugging I see the error bellow, which produces a null pointer:
Method threw 'org.mockito.exceptions.misusing.UnfinishedStubbingException' exception. Cannot evaluate org.springframework.http.ResponseEntity$$EnhancerByMockitoWithCGLIB$$3c63496d.toString()
This is the line of code that I am trying to test :
ResponseEntity<EmailEntity[]> response =
restTemplate.exchange(apiURI, HttpMethod.GET, entity, EmailEntity[].class);
EmailEntity[] partialEmailEntity = response.getBody();
response.getBody() returns a null.
This is a piece of code in my test :
#RunWith(MockitoJUnitRunner.class)
public class EmailItemReaderTest {
#Mock
private RestTemplate restTemplate;
#InjectMocks
private EmailItemReader reader;
#Before
public void setUp(){
MockitoAnnotations.initMocks(this);
}
...
...
ResponseEntity<EmailEntity> mockEntity = Mockito.spy(new ResponseEntity(mockObject, HttpStatus.OK));
doReturn(mockEntity).when(restTemplate).exchange(
Mockito.any(URI.class),
Mockito.any(HttpMethod.class),
Mockito.any(HttpEntity.class),
EmailEntity[].class);
reader.read();
I am writing a unit test for my controller that has an injected Authentication parameter
#RequestMapping(value = Mappings.PEOPLE, method = RequestMethod.POST)
public ResponseEntity<?> people(HttpServletRequest request, Authentication authentication, #RequestBody Person person) {
...
}
I don't know how to set the authenticaion inside of my test. Here is what I have so far.
#RunWith(SpringRunner.class)
public class PeopleTest {
#Before
public void setUp() {
RestAssuredMockMvc.standaloneSetup(new PeopleController());
}
#Test
public void testKanbanOnlyScan() {
SecurityContextHolder.getContext().setAuthentication(new UsernamePasswordAuthenticationToken("username", "password"));
given()
.contentType(MediaType.APPLICATION_JSON_VALUE)
.body(new Person("Davey Jones"))
.when()
.post("/people")
.then()
.statusCode(is(HttpStatus.OK.value()));
}
}
But authentication is null in my controller during the test. How can I inject authentication into a controller?
You can use MockMVC for test your controller using something like:
#Autowired
MockMVC mockMvc;
mockMvc.perform("/your-controller-path").with(authentication(authentication))
For more details take a look in spring docs
preview-spring-security-test-web-security
You can still use RestAssuredMockMvc, if you are using the WebApplicationContext.
#SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class TodoControllerTest {
#Autowired
private WebApplicationContext webApplicationContext;
#BeforeEach
void init() {
RestAssuredMockMvc.webAppContextSetup(webApplicationContext);
}
#Test
void secured_api_should_react_with_default(){
given()
.when()
.get("/todo/")
.then()
.statusCode(HttpStatus.UNAUTHORIZED.value());
}
#Test
public void secured_api_should_give_http_200_when_authorized() {
given()
.auth().with(SecurityMockMvcRequestPostProcessors.httpBasic("foo", "bar"))
.when()
.get("/todo/")
.then()
.statusCode(HttpStatus.OK.value());
}
}
I'm looking for way how to inject beans and mock in single constructor.
#Service
public class SomeService {
private EndpointUrlProvider endpointUrlProvider;
private RestTemplate restTemplate;
#Autowired
public SomeService(EndpointUrlProvider endpointUrlProvider, RestTemplate restTemplate){
this.endpointUrlProvider = endpointUrlProvider;
this.restTemplate = restTemplate;
}
Test:
class SomeTest extends Specification {
#Autowired
EndpointUrlProvider endpointUrlProvider
RestTemplate restTemplate = Mock {
postForEntity(_, _, SomeResponse.class) >> new ResponseEntity(new SomeResponse(), HttpStatus.OK)
}
SomeService someService = new SomeService(endpointUrlProvider, restTemplate)
//some tests
}
When I fire test my endpointUrlProvider in someService is null. What I did wrong ? What is the best way to test this?
As far as I see, you are trying to do partial mocking. To inject Spring beans, first you will need TestContextManager. Therefore, run the test with SpringRunner or SpringJUnit4ClassRunner. This should do the work:
#RunWith(SpringRunner.class)
public class SomeServiceTest {
#Autowired
private EndpointUrlProvider endpointUrlProvider;
#Before
public setUp() {
RestTemplate restTemplate = mock(RestTemplate.class);
SomeService someService = new SomeService(endpointUrlProvider, restTemplate);
}
}