This is my controller class
#Controller
public class myClass extends BaseController {
#RequestMapping(value = "/myList", method = RequestMethod.POST, consumes = "application/json")
public #ResponseBody MyBaseVO getMyList(#RequestBody MyBaseVO requestObj) throws Exception {
requestObj.setEntity(getConfig(LanguageConstant.MY_MODULE_ID));
MyBaseVO response = (MyBaseVO) this.execute(requestObj,LanguageConstant.MY_MODULE_ID);
return response;
}
}
I wanted to write a mock test case but stuck at this point, also i'm not sure i am doing correct or not. Can anyone help me in this.
public class myClassTest{
myClass spy = Mockito.spy(new myClass ());
Mockito.when(spy.getMyList(itemRequest)).thenReturn(itemReq);
}
I am not sure how to use url myList in testcase and request and response object. I have created a json file of my request and response. Since it is using parent class therefore I am using spy for my testcase.
Since you are using Spring, you should have a look at Spring's platform Mock Test implementation for Spring MVC.
https://docs.spring.io/spring/docs/current/spring-framework-reference/testing.html#spring-mvc-test-framework
Related
We created a common class where a RestTemplate is passed as a parameter. This rest template is used to facilitate:
postForEntity
exchange
However, since it is not Autowired in the common class, I am not able to create unit tests that mocks the RestTemplate. Is there a work around for this?
Setup:
Spring boot Project A - initiates a rest integration and utilises the common class. This Project A instantiates the #Autowired RestTemplate rest template and pass it as a parameter to the common class method.
Spring boot Common Class - conducts the rest integration but uses the rest template passed by Project A. This common class I am unable to conduct the unit test since I cannot mock the Rest Template.
This is a java spring boot project.
Addendum:
**COMMON CLASS
public class RestService {
public static void invoke(RestTemplate restTemplate, RequestDetails requestDetails) {
switch (requestDetails.getHttpMethod()) {
case POST:
HttpEntity<?> postEntity = new HttpEntity<>(request, httpHeaders);
restResponse = restTemplate.postForEntity(requestDetails.getUrl(), postEntity, String.class);
break;
case GET:
HttpEntity<?> getEntity = new HttpEntity<>(httpHeaders);
restResponse = restTemplate.exchange(requestDetails.getUrl(),
HttpMethod.GET, getEntity, String.class);
break;
default:
break;
}
}
}
** INVOKING CLASS
public class InvokingClass {
#Autowired
private RestTemplate restTemplate;
public void invoke() {
//RequestDetails construct here ...
RestService.invoke(restTemplate,requestDetails)
}
}
I'm not sure what you are trying to achieve. If you want to test your RestService you should be able to do something like this:
#Test
void test() {
RestTemplate templateMock = mock(RestTemplate.class);
RestService.invoke(templateMock, new RequestDetails());
verify(templateMock).postForEntity(any(URI.class), any(Object.class), any(Class.class));
}
If this is not what you're looking for please provide more details on what you're trying to test. Thanks.
I'm interested in overloading an #PostMapping of say, /digital/testCase, with two separate signatures, that use #RequestBody annotations to pass data, rather than #RequestParams. This is important, because all of the other questions on StackOverflow pertain to the latter. Currently, Spring Boot crashes when I try overload a function.
For those interested in seeing the code, it would look something like this
package com.example.test;
import *
#RestController
#RequestMapping(path = "/digital", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
public class TestController {
private static final Logger LOG = LoggerFactory.getLogger(TestController.class);
#Autowired
private testDomain testDomain;
#PostMapping("/testCase")
public ResponseEntity<Object> testCase(#RequestBody InitiateTestCase initiateTestCase,
HttpServletRequest request) {
//
...some code here
//
}
#PostMapping("/testCase")
public ResponseEntity<Object> testCase(#RequestBody InitiateTestCase[] initiateTestCases,
HttpServletRequest request) {
//
...some code here
//
}
}
You can try to add some specific params/headers to PostMapping annotation so Spring will be able to map it properly. Another way of solving such problem is to abstract your pojo used as RequestBody and not overload methods.
This is my Mockito Test:
#RunWith(MockitoJUnitRunner.class)
public class Controller_Test {
private MockMvc mockMvc;
#InjectMocks
private EmployeeController employeeController;
#Mock
private InputValidationService inputValidationService;
#Before
public void setup() {
MockitoAnnotations.initMocks(this);
this.mockMvc = MockMvcBuilders.standaloneSetup(restController).build();
}
#Test
public void testGetEmployeeDetails() {
EmployeeController spy = Mockito.spy(employeeController);
MvcResult result = mockMvc.perform(get("/employee/details/9816")).andDo(print()).andExpect(status().isOk()).andReturn();
// Have some basic asserts here on the result that are working fine
}
}
Now my question is, Is there a way to assert that the method I expected to be called in my controller was actually invoked.
I know it was, but how do I assert it with unit test
For e.g.
This is my RequestMapping in the controller:
#RequestMapping(value = "/employee/details/{id}", produces = "application/json; charset=UTF-8", method = RequestMethod.GET)
#ResponseStatus( HttpStatus.OK)
#ResponseBody
public EmployeeDetails getEmployeeDetailsById(#PathVariable String employeeID) {
//Some business logic
}
Now I would like to make some assertion like:
Mockito.verify(spy, times(1)).getEmployeeDetailsById();
So basically I would like to assert that the method I expected to get called was the one that got called. I know this can be done on the Mock Service object that I have i.e. inputValidationService but would like something similar for the controller as well.
Please let me know if there are any additional details that you would like me to post.
Maybe late, but I found org.springframework.test.web.servlet.result.HandlerResultMatchers which can verify the proper controller and method are being called. For example:
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.handler;
mockMvc
.perform(get("/employee/details/9816"))
.andExpect(handler().handlerType(EmployeeController.class))
.andExpect(handler().methodName("getEmployeeDetailsById"));
You can use #MockBean.This will use Mockito beans for which you will be able to use standart Mockito functions like "verify".
http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-testing-spring-boot-applications-mocking-beans
I have a controller and my requirement is to call a method of controller from a new class.
Suppose this is my method
#SuppressWarnings("unchecked")
#Timed
#RequestMapping(value = "/loadProductsRailWidget/", method = RequestMethod.GET)
public ModelAndView getProductsRailWidget(){
/////some code here
return modelAndView;
}
and I want to call this method from
public class TestRepeat {
#Timed
public void repeat() {
System.out.println("Called... AT :: " + Calendar.getInstance().getTime());
}
}
let me know how can I do this, thanks in advance.
You can create an instance of your controller from your class and invoke the method. But this will not give you any of the wired components, as this is a regular way of calling classes and its no advisable.
TestController tC = new TestController();
tC.getProductsRailWidget();
The other way is get the controller from ctx.getBean("");
I did Google a lot to find my problem but I couldn't and sorry If this question already on the stack overflow because I have not find it.
First let take a look into the code
#Controller
public class Controller1 {
#RequestMapping(value = "URL", method = RequestMethod.GET)
public ModelAndView methodHandler(Parameters) {
}
public int calculation(int i){
//Some Calcucation
return i;
}
}
and second controller is
#Controller
public class Controller2 {
#RequestMapping(value = "URL", method = RequestMethod.GET)
public ModelAndView methodHandler(Parameters) {
//In this I want to call the calculation(1) method of controller1.
}
}
My question is that is there any way to call the method of calculation() of controler1 in to controller2. But remember I don't want to make method static in controller1.Is there anyway to call it without make it static?
Thanks
Yasir
You should create service bean for example in configuration file (or use # one of the annotaions) and inject it into controller. For example ()
#Configuration
public class MyConfig {
#Bean
public MyService myService(){
return new MyService();
}
}
#Controller
public class Controller1 {
#Autowire
private MyService myService;
#RequestMapping(value = "URL", method = RequestMethod.GET)
public ModelAndView First(Parameters) {
myService.calculation();
}
}
#Controller
public class Controller2 {
#Autowire
private MyBean myBean;
#RequestMapping(value = "URL", method = RequestMethod.GET)
public ModelAndView First(Parameters) {
myService.calculation();
}
}
Your controllers should not call each other. If there is a logic which needs to be used by both controllers, it is much better to put that into separate bean, which will be used by both controllers. Then you can simply inject that bean to whicheveer controller neccessary. Try not to put any business logic to controllers, try tu put it to specialized class instead which will be web independent if possible and will accept web agnostic business data as user email, account number etc. No http request or response. This way your class with actual logic is reusable and can be unit tested much more easily. Also, if there is state, it should be contained in your classes outside controllers. Controllers should be stateless and not contail any state at all.
When using MVC pattern and you are deciding where to put your logic, you should separate business logic into model and into controllers you should put only logic regarding user interaction, as explained in this stack overflow post.