Want to Mock ValidationofToken in restcontroller junit testing - spring

Need to skip a Validation of token id login in controller for unit testing
Not sure what to use Mock or spy since i'm testing the controller itself
public class TestController extends BaseController {
#Autowired
TestService service;
#RequestMapping(value = "/test")
public #ResponseBody TestResponse getAll(#RequestBody TestRequest request) {
validateToken(request);
TestResponse response = service.getall(request);
response.setTokenID(request.getTokenID());
return response;
}
}
public class BaseController {
protected void validateToken(IRequest request) {
TokenResponse tokenresponse = restTemplate.exchange(TokenServiceURL, HttpMethod.GET, null, TokenResponse .class, tokenId).getBody();
User user = new user()
user.setUserRole(tokenresponse.getUser()));
request.setUser(user);
}
}
public class TestControllerTest {
private MockMvc mockMvc;
#Autowired
private WebApplicationContext wac;
#Autowired
private TestController testControlller;
#MockBean
private TestService testService;
BaseController baseControllerSpy = Mockito.spy(BaseController.class);
#Before
public void setUp(){
MockitoAnnotations.initMocks(this);
mockMvc = MockMvcBuilders.webAppContextSetup(wac).build();
}
#Test
public void verifygetAll() throws Exception {
TestRequest request = new TestRequest();
TestResponse response = new Response();
**Mockito.doNothing().when(baseControllerSpy).validateTokenID(request);**
when(testService.get(request)).thenReturn(response);
mockMvc.perform(MockMvcRequestBuilders.post("/test")
.contentType(MediaType.APPLICATION_JSON)
.content(requestString)
.accept(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
}
}
Base controller being spy doesn't seem to work, is there any other way i can approach this scenrio. please help

I can advice you two solutions:
I assume that if you are in the same package then you have to inject a spy of TestController in the mockMvc when you do the build() then you can create the validateToken mockMvc
doNothing().when((BaseController)testController).validateTokenID(any());
If the previous solution is not compliant then you can extend the TestController class with the TestControllerForTest and you can make the override of the validateTokenID method where you do nothing.

Related

Spring Boot Unit Testing MockMvc Null Body

I am having dificulties with using MockMvc.
Here I have simple Service and controller classes:
Service:
#Slf4j
#Service
public class EmployeeService {
//...
public Employee GetSample() {
//...
//filling Employee Entities
return new Employee(
"Harriet"
, "random"
, 25);
}
}
controller:
#RestController
#RequestMapping(value = "/info")
#RequiredArgsConstructor(onConstructor = #__(#Autowired))
#Validated
public class EmployeeController {
private final EmployeeService employeeService;
#PostMapping("/GetEmployee")
public ResponseEntity<Employee> GetEmployee() {
Employee employee = employeeService.GetSample();
return new ResponseEntity<>(employee, HttpStatus.OK);
}
}
Test:
#RunWith(SpringJUnit4ClassRunner.class)
#SpringBootTest
public class EmployeeTestCase {
private MockMvc mockMvc;
#InjectMocks
private EmployeeController EmployeeController;
#Mock
private EmployeeService employeeService;
#Before
public void setUp() {
this.mockMvc = MockMvcBuilders.standaloneSetup(employeeController).build();
}
#Test
public void getEmployee() throws Exception {
this.mockMvc.perform(MockMvcRequestBuilders.post("/info/GetEmployee")).andDo(print());
}
}
when I try to use MockMvc I get null body. It seems employee is null. But I didn't understand why.
I thought that when test uses perform, it should initialise employee and later on it should't be null.
I tried to cut the code as much as possible. I hope it is not long.
Note : also tried to use Mockito.when(employeeController.GetEmployee()).thenCallRealMethod();
The #SpringBootTest annotation loads the complete Spring application
context. That means you do not mock your layers
(Services/Controllers).
If you wanted to test specific layers of your application, you could look into test slice annotations offered by Springboot: https://docs.spring.io/spring-boot/docs/current/reference/html/test-auto-configuration.html
In contrast, a test slice annotation only loads beans required to test a particular layer. And because of this, we can avoid unnecessary mocking and side effects.
An example of a Test Slice is #WebMvcTest
#ExtendWith(SpringExtension.class)
#WebMvcTest(controllers = HelloController.class,
excludeFilters = {
#ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = SecurityConfig.class)
}
)
public class HelloControllerTest {
#Autowired
private MockMvc mvc;
#Test
public void hello() throws Exception {
String hello = "hello";
mvc.perform(get("/hello"))
.andExpect(status().isOk())
.andExpect(content().string(hello));
}
#Test
public void helloDto() throws Exception {
String name = "hello";
int amount = 1000;
mvc.perform(
get("/hello/dto")
.param("name", name)
.param("amount", String.valueOf(amount)))
.andExpect(status().isOk())
.andExpect(jsonPath("$.name", is(name)))
.andExpect(jsonPath("$.amount", is(amount)));
}
}
However if you really wanted to load up the SpringBoot Application context, say for an Integration Test, then you have a few options:
#SpringBootTest
#AutoConfigureMockMvc
public class TestingWebApplicationTest {
#Autowired
private MockMvc mockMvc;
#Test
public void shouldReturnDefaultMessage() throws Exception {
this.mockMvc.perform(get("/")).andDo(print()).andExpect(status().isOk())
.andExpect(content().string(containsString("Hello, World")));
}
}
#RunWith(SpringJUnit4ClassRunner.class)
#SpringBootTest
public class AuctionControllerIntTest {
#Autowired
AuctionController controller;
#Autowired
ObjectMapper mapper;
MockMvc mockMvc;
#Before
public void setUp() throws Exception {
System.out.println("setup()...");
mockMvc = MockMvcBuilders.standaloneSetup(controller).build();
}
#Test
public void create_ValidAuction_ShouldAddNewAuction() throws Exception {
final Auction auction = new Auction(
"Standing Desk",
"Stand up desk to help you stretch your legs during the day.",
"Johnnie34",
350.00);
mockMvc.perform(post("/auctions")
.contentType(MediaType.APPLICATION_JSON)
.content(toJson(auction)))
.andExpect(status().isCreated());
}
}
Lets say you don't want to load up any layers at all, and you want to mock everything, such as for example a Unit Test:
#RunWith(MockitoJUnitRunner.class)
class DemoApplicationTest {
#Mock
private UserRepository userRepository;
private Demo noneAutoWiredDemoInstance;
#Test
public void testConstructorCreation() {
MockitoAnnotations.initMocks(this);
Mockito.when(userRepository.count()).thenReturn(0L);
noneAutoWiredDemoInstance = new Demo(userRepository);
Assertions.assertEquals("Count: 0", noneAutoWiredDemoInstance.toString());
}
}

Testing the controller which returns response entity

I have following the controller which accepts post request and returns Response Entity with body
#RestController
public class UserController {
#Autowired
private UserService UserService;
#RequestMapping(value = "/all", method = POST,consumes = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<List<ResponseUser>> navigationTree(#RequestBody(required=false) UserDataRequest request) {
return UserService.sendEntries(request);
}
}
This is the test I wrote I for it:
#RunWith(SpringJUnit4ClassRunner.class)
#SpringBootTest
#AutoConfigureMockMvc
public class UserControllerTest {
private MockMvc mockMvc;
#MockBean
private UserService UserServiceMock;
#Autowired
private WebApplicationContext webApplicationContext;
#Before
public void setUp() {
this.mockMvc = webAppContextSetup(webApplicationContext).build();
}
#Test
public void returnTopLevel() throws Exception {
String expectedJson = "[{\"id\":\"11\",\"name\":\"11\"},{\"id\":\"22\",\"name\":\"22\"}]";
MvcResult result = this.mockMvc.perform(post("/all")
.contentType(MediaType.APPLICATION_JSON)
.content("")
.accept(MediaType.APPLICATION_JSON))
.andExpect(status().isOk()).andReturn();
String actualJson = result.getResponse().getContentAsString();
// System.out.println(result);
//assertThat(Objects.equals(expectedJson, actualJson)).isTrue();
verify(UserServiceMock,times(1)).sendEntries(null);
}
}
I want to compare string received in response body to expected string.
I tried the string comparison but it's not working
Errors :
assertThat(Objects.equals(expectedJson, actualJson)).isTrue();
and actualjson is empty.
What are the other ways?
You need to mock the UserService to return something before executing this.mockMvc.perform. Something like this:
when(UserServiceMock.sendEntries(null)).thenReturn(expectedResponceEntity);
So just construct the expected response then mock UserService to return it.

why my unit test for my rest controller method with mock doesn't work?

I try to make a dummy test of a method in my controller but doesn't work , i have a null pointer exception and i would like to know why it doesn't work, i precise that's my first time when i make this kind of tests.
This is my rest controller :
#RestController
#RequestMapping("/api")
public class AdminController {
#Autowired
private UserService userService;
#Secured(value = "ROLE_ADMIN")
#GetMapping("/roles")
public ResponseEntity<List<Role>> getRoles(){
return new ResponseEntity(userService.getRoles(), HttpStatus.OK);
}
This my controller test :
#RunWith(SpringRunner.class)
#WebMvcTest(value = AdminController.class, secure = false)
public class AdminControllerTest {
private MockMvc mvc;
#MockBean
UserService userService;
#Test
public void getRoles() throws Exception{
Role role=new Role("Admin");
List<Role> roles=Arrays.asList(role);
given(userService.getRoles()).willReturn(roles);
mvc.perform(get("/api/roles")).andExpect(status().isOk());
}
When i run the test for this method a i have this kind of error :
Thank you in advance for your help
Try this. It should work. I think you missed #Autowired annotation
#RunWith(SpringRunner.class)
#WebMvcTest(value = AdminController.class, secure = false)
public class AdminControllerTest {
#Autowired
private MockMvc mvc;
#MockBean
UserService userService;
#Test
public void getRoles() throws Exception{
Role role=new Role("Admin");
List<Role> roles=Arrays.asList(role);
given(userService.getRoles()).willReturn(roles);
mvc.perform(get("/api/roles")).andExpect(status().isOk());
}
}

Testing REST API with MOCKITO

I have a problem with testing the REST API using MOCKITO
I have an example of the rest controller code:
#RestController
#RequestMapping(path = "api/workers")
public class WorkOfferController {
#Autowired
private WorkerService workerService;
#PostMapping(value = "/lists", consumes = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity searchWorker(#RequestBody RecruitmentSearchRequest recruitmentSearchRequest, #RequestParam("page") int page, #RequestParam("size") int size,) throws NoSuchFieldException {
System.err.print('WorkerController');
return workerService.getWorkers(recruitmentSearchRequest, page, size);
}
}
And the right service for it:
#Service
#Transactional
#RequiredArgsConstructor(onConstructor = #__(#Autowired))
public class WorkerService {
private final WorkerRepistory workerRepository;
private final UserRepository userRepository;
public ResponseEntity getWorkers(RecruitmentSearchRequest recruitmentSearchRequest,int pageNumber, int size) throws NoSuchFieldException {
System.err.print('WorkerService');
...
}
}
I want to test whether everything is okay under the url with the right data. I do not want to use this database because I prefer Mockito.
#RunWith(SpringJUnit4ClassRunner.class)
#WebAppConfiguration
#SpringBootTest(classes = Appp2workApplication.class)
#FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class PharmacyWorkOfferRestDocsTests {
private MockMvc mockMvc;
#InjectMocks
private WorkOfferController workOfferController;
#Mock
private WorkerService workerService;
#Mock
UserRepository userRepository;
#Mock
WorkerRepistory workerRepository;
#Before
public void setUp() {
this.mockMvc = MockMvcBuilders.standaloneSetup(workOfferController).build();
}
#Test
public void searchWorkOfferListWithParameters() throws Exception {
String payload = "{\n" +
"\t\"name\":\"tomek\",\n" +
"\t\"searchFromSalary\":5,\n" +
"}";
Mockito.doNothing().when(userRepository.save(Mockito.anyObject()));
Mockito.when(searchService.getRecruitmentOfferJobListWithParameters(Mockito.anyObject())).thenReturn(list);
this.mockMvc.perform(post("/api/workers/lists?page=0&size=20").contentType(MediaType.APPLICATION_JSON).content(payload))
.andExpect(status().isOk());
}
}
And I have a problem that with this approach the test comes to me in the controller and displays "WorkerController" but I do not want to enter the service from this controller, and it returns 200, but it really only came to the controller and that's it. This is probably because WorkerService is as Mock but I tried to give it as eg Autowired or InjectMock and it is still the same.
What do I do wrong that I enter into the controller but I do not want to use this controller for the appropriate service?

JUnit not working in Spring Boot with #Autowired annotation

I have a Spring Boot application in which I'm creating REST web services
using the MVC pattern.
I have a controller, service and DAO class and I use the #Autowired annotation for calling methods of the service and DAO layer.
When I create JUnit tests using mockito, the values are going into the controller but from the controller they are not going to the service class.
Here is the code sample:
#WebAppConfiguration
#RunWith(SpringRunner.class)
#ContextConfiguration(classes = {AppplicationConfiguration.class})
public class ExternalControllerTest {
private MockMvc mockMvc;
#InjectMocks
private MyController myController;
#MockBean
myService myService;
#Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
mockMvc = MockMvcBuilders
.standaloneSetup(myController)
.build();
}
#Test
public void testListCluster() throws Exception {
Input emrInput = new Input();
emrInput.setId("200004773");
emrInput.setName("test");
String expected = "{\"status\":\"Success\",\"message\":\"Success\",\"data\":\"somevalue\"}";
AutomateRestResponse response = new AutomateRestResponse<JsonObject>();
response.setMessage("Success");
response.setStatus("Success");
response.setData("somevalue");
Mockito.when(
externalService.listCluster(emrInput)
).thenReturn(response);
mockMvc.perform(post("/v1/gerData"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.status", is("Success")));
verify(externalService, times(1)).listCluster(emrInput);
RequestBuilder requestBuilder = MockMvcRequestBuilders
.post("/v4/listCluster")
.accept(MediaType.APPLICATION_JSON).content(emrInputJosn)
.contentType(MediaType.APPLICATION_JSON);
MvcResult result = mockMvc.perform(requestBuilder).andReturn();
System.out.println("response body1" + result.getResponse()
.getContentAsString());
}`
Please help me with this.
It is not clear from your question what you are trying to mock.
Anyway, you should not be able to debug your service/dao that is mocked since what actually executed in the test is the mocked one and not yours.
If you want to test your controller, you can mock your service or dao and define what the response they will return, and then verify that the response you get from your controller is as you expect it to be.
#EnableWebMvc
#SpringBootApplication(scanBasePackages = { "com.yourPackage.external" })
public class YourApplication extends org.springframework.boot.web.support.SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(applicationClass, args);
}
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(applicationClass);
}
private static Class<Application> applicationClass = Application.class;
}
Based on what you have pasted, you can do below things:
if you are using #RunWith(SpringJUnit4ClassRunner.class) [better change to #RunWith(SpringRunner.class)] then use
#MockBean
private MyService externalService;
OR
use #RunWith(MockitoJUnitRunner.class) and
#MockBean
private MyService externalService;
#InjectMocks
private MyController controller = new MyController(externalService);
for details checkout :- testing web in spring boot
#WebAppConfiguration
#RunWith(SpringRunner.class)
#ContextConfiguration(classes = {AppplicationConfiguration.class})
public class ExternalControllerTest {
private MockMvc mockMvc;
#InjectMocks
private MyController myController ;
#MockBean
myService myService;
#Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
mockMvc = MockMvcBuilders
.standaloneSetup(myController)
.build();
}
#Test
public void testListCluster() throws Exception {
Input emrInput = new Input();
emrInput.setId("200004773");
emrInput.setName("test");
String expected = "{\"status\":\"Success\",\"message\":\"Success\",\"data\":\"somevalue\"}";
AutomateRestResponse response = new AutomateRestResponse<JsonObject>();
response.setMessage("Success");
response.setStatus("Success");
response.setData("somevalue");
Mockito.when(
externalService.listCluster(emrInput)
).thenReturn(response);
mockMvc.perform(post("/v1/gerData"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.status", is("Success")));
verify(externalService, times(1)).listCluster(emrInput);
RequestBuilder requestBuilder = MockMvcRequestBuilders
.post("/v4/listCluster")
.accept(MediaType.APPLICATION_JSON).content(emrInputJosn)
.contentType(MediaType.APPLICATION_JSON);
MvcResult result = mockMvc.perform(requestBuilder).andReturn();
System.out.println("response body1"+ result.getResponse()
.getContentAsString());
}
}

Resources