I am trying to test my REST endpoints using RestAssured with mocking some of the service/repositories in the controller.
this is my test class:
#RunWith(SpringJUnit4ClassRunner.class)
#Transactional
#SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = {VedicaConfig.class})
#AutoConfigureMockMvc
#ActiveProfiles("test")
public class RESTTest {
#LocalServerPort
private int port;
#Autowired
private MockMvc mvc;
#Mock
MetaVersionDAO metaVersionDAO;
#InjectMocks
DocCtrl docCtrl;
#Before
public void contextLoads() {
RestAssured.port = port;
assertThat(mvc).isNotNull();
// this must be called for the #Mock annotations above to be processed.
MockitoAnnotations.initMocks(this);
RestAssuredMockMvc.standaloneSetup(MockMvcBuilders.standaloneSetup(docCtrl));
}
#Test
public void shouldGetThumbnail() {
String ver = "1.0";
String uuid = "124-wqer-365-asdf";
when(metaVersionDAO.getMetaByVersionUUID(ver, uuid)).thenReturn(new DocVersion());
given()
.when()
.param("uuid", uuid)
.param("versionVed", ver)
.get(CTX_BASE + "/thumbnail")
.then()
.log().ifValidationFails()
.statusCode(OK.value())
.contentType(ContentType.BINARY);
}
}
now, the REST endpoint itself is being hit correctly with supplied parameters. this endpoint has DocCtrl injected which uses metaVersionDAO instance in turn:
public RawDocument getDocThumbnail(String uuid, String versionVed) throws Exception {
DocVersion docVersion = metaVersionDAO.getMetaByVersionUUID(versionVed, uuid);
InputStream inputStream = okmWebSrv.getOkmService().getContentByVersion(uuid, versionVed);
String dataType = docVersion.getMetadata().getAdditionals().get(Vedantas.CONTENT_TYPE);
ByteArrayInputStream bais = new ByteArrayInputStream(createPDFThumbnail(dataType, inputStream));
RawDocument rawDocument = new RawDocument(bais, "qwer");
return rawDocument;
}
as you can see, I have tried to mock metaVersionDAO at the top of the #Test method so I expected it to return new DocVersion() as I set it to, but in this DAO the actual code is being called and it fails on entityManager which is null.
My question is why metaVersionDAO.getMetaByVersionUUID doesn't return my mocked object and what should I do to make it so?
spring-mock-mvc: 3.3.0
spring-boot: 2.1.2.RELEASE
Thanks!
solved by changing #Mock for #MockBean.
so it is:
#MockBean
MetaVersionDAO metaVersionDAO;
everything else remains the same as in the post and it uses mocked instance.
Related
I am writing a simple test for a controller endpoint.
It works fine when I do the following.
#SpringBootTest
#ContextConfiguration(classes = {
HomeController.class,
HomeControllerTest.class
})
class HomeControllerTest {
#Autowired
private WebApplicationContext webApplicationContext;
private static final String URL = "/a";
private static final ObjectMapper objectMapper = new ObjectMapper();
#Test
public void test() throws Exception {
MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
Request request = new Request();
mockMvc.perform(post(URL)
.contentType("application/json")
.content(objectMapper.writeValueAsString(request))
.andExpect(status().isOk());
}
}
But I do not want to have to create the mockMvc and concern with webApplicationContext.
Thus instead, attempting to use #AutoConfigureMockMvc instead as follows.
But this doesn't work. Fails with following error.
java.lang.AssertionError: Status expected:<200> but was:<403> Expected
:200 Actual :403
What am I doing wrong?
My attempt which throws above error.
#SpringBootTest
#AutoConfigureMockMvc // using this annotation instead
#ContextConfiguration(classes = {
HomeController.class,
HomeControllerTest.class
})
class HomeControllerTest {
// wiring mockMvc instead
// no webApplicationContext autowired
#Autowired
private MockMvc mockMvc;
private static final String URL = "/a";
private static final ObjectMapper objectMapper = new ObjectMapper();
#Test
public void test() throws Exception {
Request request = new Request();
mockMvc.perform(post(URL)
.contentType("application/json")
.content(objectMapper.writeValueAsString(request))
.andExpect(status().isOk());
}
}
Try create test like this exemple it is better.
#SpringBootTest
#AutoConfigureMockMvc
public class HomeControllerTest
private ObjectMapper mapper;
private MyControler myController;
private ServiceInSideConttroler service;
add your atributes
#Before
public init(){
this.mapper = new ObjectMapperConfiguration().mapper();
this.service = mock(ServiceInSideConttroler.class);
this.myController = new MyController(service);
}
#Test
public void test() throws Exception {
// exemple how mock reponse from any service or repository.
when(service.findById(any(Long.class)))
.thenReturn(Optional.of(budget));
Object resp = myController.save(mockben());
......
aserts(resp)
}
}
Remember, to work with the tests like this, do not use #Authwired in the attributes, only in the constructor of the classes annotated with #service, #componet, #controller etc .... that is, any class controlled by Spring that will use dependecia injection. Also rember asserts your reponse.
I'm working with Eureka and I have a Method that uses the DiscoveryClient to obtain the instances of a service and the call this service and retrieve some information like this:
List<ServiceInstance> instances = discoveryClient.getInstances(CSC_APP_NAME);
ServiceInstance serviceInstance = instances.get(0);
String baseUrl = serviceInstance.getUri().toString();
baseUrl = baseUrl + usrEmail + "/services";
ResponseEntity<Service> response = restTemplate.getForEntity(baseUrl, Service.class);
It works, but now I want to make a JUnit test for the method and as I'm not going to have the Eureka working in the JUnit test environment, I think I should mock the discoveryClient, but how should I make this mock? I'm using mockito in the project.
It's correct to mock the discoveryClient in the unit test. Using Junit 5:
public class MyServiceTest {
#InjectMocks
private MyService myService;
#Mock
private DiscoveryClient discoveryClient;
#Mock
private RestTemplate restTemplate;
#BeforeEach
public void initTest() {
MockitoAnnotations.initMocks(this);
}
#Test
public void myTest() {
ServiceInstance si = mock(ServiceInstance.class);
when(si.getUri()).thenReturn(URI.create("myUri"));
when(discoveryClient.getInstances(anyString()))
.thenReturn(List.of(si));
myService.myMethod();
}
}
I also mocked the restTemplate, but that is up to you. MyService.myMethod() implementation:
public void myMethod() {
List<ServiceInstance> instances =discoveryClient.getInstances("CSC_APP_NAME");
ServiceInstance serviceInstance = instances.get(0);
String baseUrl = serviceInstance.getUri().toString();
baseUrl = baseUrl + "userEmail" + "/services";
ResponseEntity<Service> response = restTemplate.getForEntity(baseUrl, Service.class);
}
I'm new to unit tests and well, I'm struggling to understand how it should be done.
I have some methods with #RequestParam and I'm not sure how to mock this.
It would be great if I had an example I could apply to the other methods.
Could you help me by writing the test method for this one? It would be very useful.
#PutMapping("/player/update-password")
public ResponseEntity<?> updatePlayerPassword(#RequestParam("token") String token, #RequestParam("password") String newPassword) throws URISyntaxException {
String message = bundle.getString("put_player");
log.debug(message, token, newPassword);
PlayerEntity player = playerService.updatePassword(token, newPassword);
return new ResponseEntity<>(PlayerMapper.INSTANCE.mapPlayer(player), HttpStatus.ACCEPTED);
}
Thanks.
You can use #Mock and #InjectMocks annotations. With it you can inject mocks to your controller.
#Mock
PlayerService playerServiceMock;
And use when().then() from Mockito inside test or method with #Before annotation:
when(playerServiceMock.updatePassword(anyString(), anyString())).thenReturn(playerEntity);
The same can be done for bundle.getString("put_player").
Hoping you are using the Mockito. You can try the below code, need to add all imports
#RunWith(MockitoJUnitRunner.class)
#SpringBootTest(webEnvironment = WebEnvironment.MOCK)
public class YourClassNameTest {
#Autowired
MockMvc mockMvc;
#InjectMocks
YourClassName yourClassName;
#Mock
PlayerService playerService;
#Before
public void Setup() {
mockMvc = MockMvcBuilders.standaloneSetup(yourClassName);
}
#Test
public void updatePlayerPasswordTest() throws Exception {
PlayerEntity player = new PlayerEntity();
// set some date if you want
Mockito.when(playerService.updatePassword(anyString(), anyString())).thenReturn(player);
RequestBuilder requestBuilder = MockMvcRequestBuilders
.get("/player/update-password?token=abc&password=test")
.accept(MediaType.APPLICATION_JSON);
mockMvc.perform(requestBuilder).andExpect(MockMvcResultMatchers.status().isCreated());
}
}
I have a actually create simple webservice and i want to add new junit test.
I have a method where I add people to teams.
This is my method(in rest controller):
#PostMapping("/addPeopleToTeams/{teamId}/{personId}")
#ResponseBody
public ResponseEntity<?> addPeopleToTeam(#PathVariable Long teamId, #PathVariable Long personId) {
TeamsAndPersonsId teamsAndPersonsId = new TeamsAndPersonsId(personId, teamId);
teamService.findTeamById(teamsAndPersonsId.getTeamId());
personService.findById(teamsAndPersonsId.getPersonId());
teamService.addPersonsToTeams(personId, teamId);
return ResponseEntity.ok(teamsAndPersonsId);
}
For this method i want to wrote a Junit test but something is going wrong:/
This is my test class with method:
#RunWith(SpringRunner.class)
#SpringBootTest
#AutoConfigureMockMvc
public class TeamControllerTest {
private ObjectMapper mappingObject = new ObjectMapper();
private MockMvc mockMvc;
#Mock
private TeamService teamService;
private PersonService personService;
#Before
public void initTest() {
mockMvc = MockMvcBuilders
.standaloneSetup(new TeamController(teamService, personService))
.setControllerAdvice(GlobalExceptionHandler.class)
.build();
}
#Test
public void shouldAddPersonToTeam() throws Exception{
TeamDto teamDto = prepareTeamDto();
PersonDto personDto = new PersonDto(1L, "Bob", "Noob", "mail#first.pl", "Warszawa", "APPS", "Developer");
doNothing().when(teamService).createTeam(teamDto);
doNothing().when(personService).addPerson(personDto);
mockMvc.perform(post("/addPeopleToTeams/{teamId}/{personId}",1,1))
.andExpect(status().isOk());
}
private TeamDto prepareTeamDto() {
return new TeamDto(1L, "Jan", "local", "wawa", 6);
}
Actually for this method i have this error:
org.mockito.exceptions.base.MockitoException:
Only void methods can doNothing()!
Example of correct use of doNothing():
doNothing().
doThrow(new RuntimeException())
.when(mock).someVoidMethod();
Above means:
someVoidMethod() does nothing the 1st time but throws an exception the 2nd time is called
doNothing() is used only for void methods, like is described in your error message, in your case you have to use something like:
when(teamService.createTeam(teamDto)).thenReturn(Reponse.ok().build());
Note: you have to override #equals method in your TeamDto class
Based on the error, I guess that TeamService.createTeam or PersonService.addPerson does not have void return type and you can mock doNothing behaviour only on methods, which returns void. Also you are missing #Mock annotation on PersonService field.
In spring boot tests, it is better to use #MockBean annotation. And for controller tests it is better to use #WebMvcTest, you can then skip the configuration done in your setup method:)
#InjectMocks
Controller controllerMock;
#Before
public void setup() {
MockitoAnnotations.initMocks(this);
this.mockMvc = MockMvcBuilders.standaloneSetup(controllerMock).build();
}
where - ControllerMock will be Mock of Controller class
I am trying to test a RestTemplate exchange with a response entity in a controller from a rest Service in another application. My Junit test is coming back with a null ResponseEntity. I have tried a couple ways with no luck. First tried using mockito to mock response methods (when...then). Second tried with Exchange matchers. I also tried to mix the two with no luck. Any help would be great. Here is my Controller response I am creating:
ResponseEntity<RestResult<List<SiteMessage>>> response = rest.exchange(getAllMessagesUrl, HttpMethod.GET,
HttpEntity.EMPTY, new ParameterizedTypeReference<RestResult<List<SiteMessage>>>() {
});
Here is my Junit Test:
#RunWith(MockitoJUnitRunner.class)
#SpringBootTest
public class MessageControllerTests {
#InjectMocks
MessageController messageController;
#Mock
RestTemplate restTemplate;
#Mock
SiteMessageService serviceMock;
#Mock
ResponseEntity<RestResult<List<SiteMessage>>> response;
private MockMvc mockMvc;
#Before
public void setUp() throws Exception {
mockMvc = MockMvcBuilders.standaloneSetup(messageController).build();
}
#Test
public void testListPage() throws Exception {
RestResult<List<SiteMessage>> result = new RestResult<>();
result.setMessage("success");
SiteMessage message1 = new SiteMessage();
SiteMessage message2 = new SiteMessage();
message1.setId("ldsf030j2ldjs");
message2.setId("ldsf0432234s");
List<SiteMessage> messageList = new ArrayList<>();
messageList.add(message1);
messageList.add(message2);
result.setResults(messageList);
when(response.getBody()).thenReturn(result);
when(response.getStatusCode()).thenReturn(HttpStatus.NOT_FOUND);
when(restTemplate.exchange(
Matchers.any(URI.class),
Matchers.eq(HttpMethod.GET),
Matchers.any(),
Matchers.<ParameterizedTypeReference<RestResult<List<SiteMessage>>>>any())
).thenReturn(response);
mockMvc.perform(get("/message/list")).andExpect(status().isOk()).andExpect(view().name("message/list"));
}
}
I am trying to return a response with a body containing a RestResult object, which has a list of messages and a message