Mock a particular method in DAO layer in junit - junit

I have an application with rest api endpoints. I want to write test cases for that. It follows MVC architecture. For one of the end points I want to mock a method in my DAO class.
Sample code for my test class is:
RequestBuilder requestGetBuilder = MockMvcRequestBuilders
.get("/processcal/getdata/srn/{srn}",1000)
.contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON);
This controller will call the DAO layer having that method to be mocked.
I tried using the mockito as below in my Test config class:
#Bean
#Primary
BookMarkDao bookMarkDao() {
final BookMarkDao bookMarkDao = Mockito.mock(BookMarkDao.class);
Mockito.when(bookMarkDao.fetchMrPostProcessCalc(Mockito.anyString()))
.thenReturn(TestUtils.getMockResponse());
return bookMarkDao;
}
The problem with this is it's mocking the entire DAO bean so for rest of the endpoints its not calling the DAO class methods and my test coverage reduces. Is there a way around solving this?

You can use a specific profile for mocked beans and activate this profile in necessary test cases. By the way, if your application based on the spring-boot then you can use #MockBean instead of manual making a mock of your DAO in test configurations.

Related

Junit test case with Mockito

I am creating junit test cases for my project. I have the below code, where I would like to create a mock,
String propertyFilePath = System.getProperty("path.to.properties");
Resource propertyFile = new FileSystemResourceLoader().getResource(propertyFilePath);
Properties properties = PropertiesLoaderUtils.loadProperties(propertyFile);
I am using junit and mockito-core jar. I tried with below code,
System.setProperty("path.to.properties", "dummyPathToProperties"); //invalid Path
Properties properties = mock(Properties.class);
Resource propertyFile = new FileSystemResourceLoader().getResource("dummyPathToProperties");
when(PropertiesLoaderUtils.loadProperties(propertyFile)).thenReturn(properties);
With above code it throws error when mocking loadProperties method. How can I mock a spring static class and return my mock properties object ?
Any help will be really appreciated.
Mocking static methods requires you to go down the full nine yards and make use of PowerMock. The exact steps to mock static methods are outlined in their documentation for example.
In essence:
Use the #RunWith(PowerMockRunner.class) annotation at the class-level of the test case.
Use the #PrepareForTest(ClassThatContainsStaticMethod.class) annotation at the class-level of the test case.
Use PowerMock.mockStatic(ClassThatContainsStaticMethod.class) to mock all methods of this class.
Use PowerMock.replay(ClassThatContainsStaticMethod.class) to change the class to replay mode.
Use PowerMock.verify(ClassThatContainsStaticMethod.class) to change the class to verify mode.
But of course: consider not using PowerMock; by changing your code so that you don't have to mock the static call. But of course, it is kinda weird to add a wrapper around such a framework-provided static method.

Programmatically instantiate a FeignClient for tests

I have a dead simple FeignClient interface that I would like to "unit"/integration test with a fake HTTP server, WireMock for example. The idea is to test the mapping with a sampled HTTP API response, without configuring a whole Spring Boot/Cloud Context.
#FeignClient(name = "foo", url = "${foo.url}")
public interface FooClient {
#RequestMapping(value = "/foo/{foo-id}/bar", method = RequestMethod.GET)
public Bar getBar(#PathVariable("foo-id") String fooId);
}
Is there any way to programmatically instantiate this interface, like a Spring Data Repository through a *RepositoryFactoryBean ?
I see a FeignClientFactoryBean in the source code, but it is package protected, and it relies on an ApplicationContext object to retrieve its dependencies anyway.
Well, you can fake a real rest client using wiremock for testing purposes, but this is more about containing the functional test, that feign clients themself work. This is mostly not what you really want to test, because the actual need is to test your components using your client behave in a specified way.
The best practice for me is not to make live hard with maintaing a fake server, but mock the clients behavior with Mockito. If you use Spring Boot 1.4.0, here is the way to go:
Consider you have some FooBarService, which internally uses your FooClient to peform some FooBarService::someAction(String fooId), which performs some business logic which needs to work with a foo with given id
#RunWith(SpringRunner.class)
#SpringBootTest(classes = App.class)
class FooUnitTest {
#Autowired;
private FooBarService fooBarService;
#MockBean;
private FooClient fooClient;
#Test
public void testService() {
given(fooClient.getBar("1")).willReturn(new Bar(...));
fooBarService.someAction("1");
//assert here, that someAction did what it supposed to do for that bar
}
}
At this point you first should clarify, what you expect the REST client to respond, when asking for "/foo/1/bar", by creating a mock for exactly that case and give the Bar object you expect to receive for that API, and assert that your application is in the desired state.

Deep / Nested Dependency Injection in testing

I am using junit, mockito and mockMVC to test the working of a webapp. I am struggling with a dependency whose injecttion I cannot figure out. My webapp structure is as follows.
Class Controller{
#Autowired Service searchService;
#RequestMapping("Search")
public returnType search(#RequestParam("parameter")String parameter){
searchService.doSearch(parameter);
}
}
and the service class
Class Service{
#Autowired Service2 service2;
public returnType doSearch(String parameter){
//some code
service2.call(parameter);
}
}
I need to test the search method for this controller, however service2 is not currently live and hence calls to it have to be mocked. I can mock service2, but cannot figure out how to inject a mock of service2 in my mockMVC instance of controller. As far as I know #InjectMocks in mockito only injects mocks one level deep and not two.
EDIT:
I am using the following to get MockMVC instance of controller
MockMvc controller;
controller = MockMvcBuilders.standaloneSetup(Controller);
What you are essentially want to do is mock a bean.
In your case, you have to mock bean for service2 using #MockBean annotations.
Please refer this article for details.
You don't need that.
Mocking search service will be sufficient as you get the handle of what needs to be done.
Example:
doReturn(...).when(searchService).doSearch(any());
While performing Unit Testing, the developer need to identify the System Under Test and mock/stub all the collaborators.
So, in this case you would write a separate unit test for Controller and Search Service.
Also, read this brilliant article by Martin Fowler - Mocks Aren't Stubs.

Spring-test and ServletContextListener in web.xml

i try to use spring-test(3.2.10) and integration tests with TestNG by this link.
I created RootTest.java
#WebAppConfiguration
#ContextConfiguration("file:src/test/resources/root-context2.xml")
public class ReferenceServiceTest extends AbstractTestNGSpringContextTests {
...
spring context loaded success. But my global variables not instantiated because web.xml ignored. In web.xml i have my own "listener-class"(implementation of ServletContextListener) and "context-param". How i can load web.xml context(and calls all application startup listeners) with spring integration test context?
As stated in the reference manual, the Spring MVC Test Framework...
"loads the actual Spring configuration through the TestContext
framework and always uses the DispatcherServlet to process requests
thus approximating full integration tests without requiring a running
Servlet container."
The key point there is "without ... a Servlet container". Thus web.xml does not come into the picture here. In other words, there is no way for configuration in web.xml to have an affect on integration tests using the Spring MVC Test Framework.
Now, having said that, it is possible to register a Servlet Filter with MockMvc like this:
mockMvcBuilder.addFilters(myServletFilter);
or
mockMvcBuilder.addFilters(myResourceFilter, "/resources/*");
And you can configure context-param entries by adding them manually to the ServletContext (which is actually Spring's MockServletContext) before you execute assertions on MockMvc like this:
wac.getServletContext().setInitParameter(name, value);
But... there is no way to configure a ServletContextListener using Spring MVC Test. If you want to have a listener applied to all of your requests that pass through Spring MVC, as an alternative you could consider implementing a custom HandlerInterceptor or WebRequestInterceptor (see Configuring interceptors in the reference manual).
Regards,
Sam
Try with a MockServletContext
#Before
public void before() {
MockServletContext mockServletContext = new MockServletContext();
mockServletContext.setInitParameter("parameterName", "parameterValue");
new MyListenerClass().contextInitialized(new ServletContextEvent(mockServletContext));
}

Mocking #UriInfo using EasyMock or PowerMock

I have a REST service class in which uriInfo object is automatically injected through #UriInfo annotation. Now, while writing JUnit for this class, I want to get a mock object created for this UriInfo object without introducing any new setter methods into the tested class just for the sake of setting the mocked UriInfo into it. Kindly let me know if you have any suggestions. We are using EasyMock and PowerMock.
You can use Powermock's Whitebox to modify the internal state of an object. One of the simplest invocations is:
Whitebox.setInternalState(tested, myMock);