How can to mock the method .exchangeToMono().toFuture()? - java

Tell me how mock the method .exchangeToMono().toFuture()
My example:
public class MyExample {
private final WebClient webClient = WebClient.create();
private CompletableFuture<Result> getValue(Request request) {
return webClient
.post().uri(request.getRequiredParameter(API_URL_PARAM))
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
.header(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE)
.bodyValue(request)
.acceptCharset(StandardCharsets.UTF_8)
.exchangeToMono(rs -> Mono.just(rs.mutate().build()))
.toFuture()
}}
My test but it is not finished I do not understand how to create a mock on
.exchangeToMono(rs -> Mono.just(rs.mutate().build())).toFuture()
public class MyTest {
#Mock
private WebClient webClient;
#Mock
private WebClient.RequestBodyUriSpec requestBodyUriSpecMock;
#Mock
private WebClient.RequestBodySpec requestBodySpecMock;
#SuppressWarnings("rawtypes")
#Mock
private WebClient.RequestHeadersSpec requestHeadersSpecMock;
#Mock
private CompletableFuture<ClientResponse> responseFuture;
#Mock
private Mono<ClientResponse> clientResponseMono;
#Mock
private WebClient.ResponseSpec responseSpecMock;
#Before
public void setUp() {
when(webClient.post()).thenReturn(requestBodyUriSpecMock);
when(requestBodySpecMock.header(anyString(), anyString())).thenReturn(requestBodySpecMock);
when(requestBodySpecMock.acceptCharset(StandardCharsets.UTF_8)).thenReturn(requestBodySpecMock);
when(responseSpecMock.bodyToMono(ClientResponse.class)).thenReturn(clientResponseMono);
}
#Test
public void myTest() throws Exception {
// given
String responseBody = "{name: 'TEST'}";
when(requestBodyUriSpecMock.uri(API_URL_VALUE)).thenReturn(requestBodySpecMock);
when(requestBodySpecMock.bodyValue(responseBody)).thenReturn(requestHeadersSpecMock);
//when(clientResponseMono.block().statusCode()).thenReturn(HttpStatus.OK);
//when(responseFuture.toCompletableFuture()).thenReturn(CompletableFuture.completedFuture(responseSpecMock));}
how to complete a test for a method?

Related

Test mocking return empty body

I am trying to make testings for my user controller but when I run the test it fails because the response body is empty.
Note that the response code is 200 so i dont see where this problem comes from...
#WebMvcTest(controllers = {UserRestController.class})
public class UserControllerTest {
#Autowired
private WebApplicationContext webApplicationContext;
#MockBean
private UserService service;
private MockMvc mockMvc;
private User user1;
private User user2;
#BeforeEach
public void setUp() {
mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
this.user1 = User.builder()
.email("doe.jean#mymel.com")
.username("Djin")
.build();
this.user2 = User.builder()
.email("doe.john#mymel.com")
.username("Jodo")
.build();
}
#Test
public void test_shouldReturnAllUsers() throws Exception {
Mockito.when(service.getUsers(Pageable.unpaged())).thenReturn(new PageImpl<>(Arrays.asList(user1, user2)));
MvcResult mvcResult = mockMvc.perform(MockMvcRequestBuilders.get(APIPaths.V1_USER_BASE + "/all")
.accept(MediaType.APPLICATION_JSON))
.andExpect(request().asyncStarted())
.andReturn();
mockMvc.perform(asyncDispatch(mvcResult))
.andExpect(status().is(200))
.andExpect(jsonPath("$.size()", Matchers.is(2)))
.andDo(print());
}
}

NullPointerException in TestCode when using restTemplate and jparepository

Here is my Code
NullPointerException occurs in using restTemplate and postsRepository.
#ExtendWith(SpringExtension.class)
#SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class PostsApiControllerTest {
#LocalServerPort
private int port;
#Autowired
private TestRestTemplate restTemplate;
#Autowired
private PostsRepository postsRepository;
#Test
public void register_posts() throws Exception{
// ...
ResponseEntity<Long> responseEntity = restTemplate.postForEntity(url,requestDto,Long.class);
List<Posts> all = postsRepository.findAll();
}

Mock Service class that has Autowired dependencies

I have a Service class & a config class as below:
public class MyService{
#Autowired
MyConfig myconfig;
#Autowired
private WebClient webClient;
private String result;
public String fetchResult(){
return webClient.get().uri(myConfig.getUrl()).retrieve().bodyToMono(String.class).block();
}
}
#ConfigurationProperties("prefix="somefield")
#Component
class MyConfig{
private String url;
//getter & setter
}
}
Below is the Junit:
#Runwith(MockitoJUnitRunner.class)
public class TestMe{
#InjectMocks
MyService myService;
#Test
public void myTest(){
when(myService.fetchResult().then return("dummy");
}
}
I am getting null pointer error when I run this class at webClient in Service class.
What could be the issue. I am new to JUnits.
How do I write a proper JUnit for this.
The easiest way to make the class testable is to use constructor injection
public class MyService{
private final MyConfig myconfig;
private final WebClient webClient;
private String result;
#AutoWired
MyService(
MyConfig myconfig,
WebClient webClient
) {
this.myconfig = myconfig;
this.webClient = webClient;
}
...
}

How to write unit test for controller in spring boot

I am new to Unit testing and TDD. I want to apply unit testing for my controller and service class which i have written in spring boot.
I have implemented test class using a tutorial. However, I could not implemented it successfully. I have included my current code.
Controller
#RestController
#RequestMapping("/api")
public class MyController {
private static final Logger LOGGER = LoggerFactory.getLogger(AdminController.class);
#Autowired
MyService myService;
#PostMapping("/create")
public ResponseEntity<?> createUser(#RequestHeader("Authorization") String token,
#RequestBody User user){
ResponseDTO finalResponse = new ResponseDTO();
try {
ResponseEntity<?> entity = myService.create(token, user);
finalResponse.setMessageCode(entity.getStatusCode());
finalResponse.setMessage("Success");
finalResponse.setError(false);
ResponseEntity<ResponseDTO> finalEntity = ResponseEntity.ok().body(finalResponse);
return finalEntity;
} catch (Exception e) {
finalResponse.setMessageCode(HttpStatus.EXPECTATION_FAILED);
finalResponse.setMessage(e.getMessage());
finalResponse.setError(true);
ResponseEntity<ResponseDTO> finalEntity =
ResponseEntity.ok().body(finalResponse);
return finalEntity;
}
}
ResponseDTO
public class ResponseDTO {
private HttpStatus messageCode;
private String message;
private String messageDetail;
private Object body;
private boolean error;
//setters and getters
}
Current Test Class
#RunWith(SpringRunner.class)
public class MyControllerTest {
private MockMvc mockMvc;
#InjectMocks
private MyController myController;
#Before
public void setUp() throws Exception {
mockMvc = MockMvcBuilders.standaloneSetup(myController).build();
}
#Test
public void testCreateUser() throws Exception {
mockMvc.perform(post("/api/create")
.accept(MediaType.APPLICATION_JSON))
.andExpect(status().isCreated())
.andExpect(jsonPath("$.*", Matchers.hasSize(1)));
}
}
When i run test class i am getting WARN Resolved [org.springframework.web.bind.MissingRequestHeaderException: Missing request header 'Authorization' for method parameter of type String]
What am i doing wrong here? Any help would be grateful.
Your test could be something like this:
#Test
public void testCreateUser() throws Exception {
mockMvc.perform(post("/api/create")
.accept(MediaType.APPLICATION_JSON)
.header("AUTH_TOKEN", TOKEN)
.content(ObjectToJsonUtil.convertObjectToJsonBytes(user)))
.andExpect(status().isCreated())
.andExpect(jsonPath("$.*", Matchers.hasSize(1)));
}
you'll have to convert object user to json.
So you create a util class for this:
public class ObjectToJsonUtil {
public static byte[] convertObjectToJsonBytes(Object object)
throws IOException {
ObjectMapper mapper = new ObjectMapper();
mapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY);
JavaTimeModule module = new JavaTimeModule();
mapper.registerModule(module);
return mapper.writeValueAsBytes(object);
}
}
Hope it helps!
There are a few issues with your test:
1. Request mapping
#PostMapping("/create")
public ResponseEntity<?> createUser(
#RequestHeader("Authorization") String token,
#RequestBody User user)
only matches POST requests that have an HTTP header named Authorization and a request body that can be serialized to User. These are not optional. If they are optional, you should explicitly declare that:
#PostMapping("/create")
public ResponseEntity<?> createUser(
#RequestHeader(name = "Authorization", required = false) String token,
#RequestBody(required = false) User user) {
Assuming that they are required, you should setup MockMvc to send both to your controller:
#Test
public void testCreateUser() throws Exception {
mockMvc.perform(
post("/api/create")
.header("Authorization", "XYZ")
.content("{\"firstName\": \"James\", \"lastName\": \"Gosling\"}")
.accept(MediaType.APPLICATION_JSON)
)
.andExpect(status().isCreated())
.andExpect(jsonPath("$.*", Matchers.hasSize(1)));
}
here I have assumed your User class is like this:
public class User {
private String firstName;
private String lastName;
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
}
2. Content-Type header
Also, you should set the content type header for your MockMvc request, otherwise the test will fail with 415 - Unsupported Media Type. So your test should look like this:
#Test
public void testCreateUser() throws Exception {
mockMvc.perform(
post("/api/create")
.header("Authorization", "XYZ")
.header("Content-Type", "application/json")
.content("{\"firstName\": \"James\", \"lastName\": \"Gosling\"}")
.accept(MediaType.APPLICATION_JSON)
)
.andExpect(status().isCreated())
.andExpect(jsonPath("$.*", Matchers.hasSize(1)));
}
3. Mocked dependencies
Apart from that, in your test you have annotated MyController with #InjectMocks but you haven't mocked its MyService' dependency. That will set themyServicefield of your controller tonull. To fix that you need to mockMyService' too:
#RunWith(SpringRunner.class)
public class MyControllerTest {
private MockMvc mockMvc;
// Mock
#Mock
private MyService myService;
#InjectMocks
private MyController myController;
#Before
public void setUp() throws Exception {
mockMvc = MockMvcBuilders.standaloneSetup(myController).build();
}
#Test
public void testCreateUser() throws Exception {
// Configure mock myService
when(myService.create(anyString(), any(User.class))).thenReturn(new ResponseEntity<>(HttpStatus.CREATED));
mockMvc.perform(
post("/api/create")
.header("Authorization", "XYZ")
.header("Content-Type", "application/json")
.content("{\"firstName\": \"James\", \"lastName\": \"Gosling\"}")
.accept(MediaType.APPLICATION_JSON)
)
.andExpect(status().isCreated())
.andExpect(jsonPath("$.*", Matchers.hasSize(1)));
}
}
4. MyService does not satisfy the test conditions
When everything is hunky dory your controller responds with:
ResponseEntity<ResponseDTO> finalEntity = ResponseEntity.ok().body(finalResponse);
which will return a status code of 200. So you either have to modify your test to expect that:
.andExpect(status().isOk())
or you should update your controller to return with the 201 status code:
ResponseEntity<ResponseDTO> finalEntity = ResponseEntity.created(null).body(finalResponse);

How to test file upload in spring boot?

I have implemented a rest service similar to this one.
UserController.java
#RestController
#RequestMapping(path = "/user")
public class UserController {
private final UserService userService;
#Autowired
public UserController(UserService userService) {
this.userService = userService;
}
#PostMapping(path = "/{id}/avatar")
public void handleUpload(#PathVariable("id") int id, #RequestParam("file") MultipartFile file) {
if (file == null) {
throw new DashboardException("Please select a valid picture");
}
userService.setAvatar(id, file);
}
}
Now I am trying to test the rest endpoint with:
UserControllerEndpointTest.java
#RunWith(SpringRunner.class)
#SpringBootTest(classes = Application.class)
#WebAppConfiguration
public class UserControllerEndpointTest {
private static final int userId = 42;
private static final String urlPath = String.format("/user/%d/avatar", userId);
private MockMvc mockMvc;
#Autowired
private WebApplicationContext webApplicationContext;
#Autowired
private UserController controller;
private UserService service;
#Before
public void setUp() throws NoSuchFieldException, IllegalAccessException {
mockMvc = webAppContextSetup(webApplicationContext).build();
service = Mockito.mock(UserService.class);
injectField(controller, "userService", service);
}
#Test
public void successfullySetAvatar() throws Exception {
final InputStream inputStream = Thread.currentThread().getContextClassLoader().getResourceAsStream("test.png");
final MockMultipartFile avatar = new MockMultipartFile("test.png", "test.png", "image/png", inputStream);
doNothing().when(service).setAvatar(userId, avatar);
final MvcResult result = mockMvc.perform(fileUpload(urlPath).file(avatar))
.andExpect(status().isOk())
.andReturn();
verify(service).setAvatar(userId, avatar);
}
}
This fails with 400 - Required request part 'file' is not present.
What am I missing?
Probably you need to change
new MockMultipartFile("test.png", "test.png", "image/png", inputStream);
to
new MockMultipartFile("file", "test.png", "image/png", inputStream);
as the uploaded file parameter name is 'file'

Categories