I have 3 services
class Service1{
#Inject private Service2 service2;
}
class Service2{
#Inject private Service3 service3;
}
class Service3{
public Object test(){
...}
}
class TestService1{
//do a test and mock the method in service3
when(service3.test()).doReturn(Something());
}
I have to mock the method in service 3 injected in service 2 which is injected in service 1
any idea? I have to test it directly like that I have no other way to do it.
As the last service is a call to a rest Service, i created an interface IServiceC then 2 implementations of it, one in the main/src/java, another in test/src/java and all services are returned hardcoded values. because the complexity here is to say ok i will inject all service but not the last, and tell to second layer i inject you but i mock you too etc...
very too complicated to manage, with a mock class implementation i don't have to cary about this topic, i use arquillian and all will be injected (i exclude from the war package the default implementation and add the mock implementation to the war)
Related
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.
I was using #RunWith(MockitoJUnitRunner.class) for my junit test with mockito. But now i am working with spring boot app and trying to use #RunWith(SpringRunner.class) . Does using #RunWith(SpringRunner.class) has any advantages over using #RunWith(MockitoJUnitRunner.class)? Can i still use feature like #Injectmock, #Mock, #Spy with #RunWith(SpringRunner.class)
The SpringRunner provides support for loading a Spring ApplicationContext and having beans #Autowired into your test instance. It actually does a whole lot more than that (covered in the Spring Reference Manual), but that's the basic idea.
Whereas, the MockitoJUnitRunner provides support for creating mocks and spies with Mockito.
However, with JUnit 4, you can only use one Runner at a time.
Thus, if you want to use support from Spring and Mockito simultaneously, you can only pick one of those runners.
But you're in luck since both Spring and Mockito provide rules in addition to runners.
For example, you can use the Spring runner with the Mockito rule as follows.
#RunWith(SpringRunner.class)
#SpringBootTest
public class MyTests {
#Rule
public MockitoRule rule = MockitoJUnit.rule();
#Mock
MyService myService;
// ...
}
Though, typically, if you're using Spring Boot and need to mock a bean from the Spring ApplicationContext you would then use Spring Boot's #MockBean support instead of simply #Mock.
When SpringRunner.class is used, Spring provides corresponding annotations:
#MockBean
#SpyBean
Mocks are injected to objects under tests via #Autowired annotation. To enable this functionality tests must be annotated with
#SpringBootTest
or
#TestExecutionListeners(MockitoTestExecutionListener.class)
More details and examples can be found in the official documentation: Mocking and Spying Beans
As per the JavaDoc:
SpringRunner is an alias for the SpringJUnit4ClassRunner.
To use this class, simply annotate a JUnit 4 based test class with #RunWith(SpringRunner.class).
If you would like to use the Spring TestContext Framework with a runner other than this one, use org.springframework.test.context.junit4.rules.SpringClassRule and org.springframework.test.context.junit4.rules.SpringMethodRule.
And the JavaDoc of TestContext:
TestContext encapsulates the context in which a test is executed, agnostic of the actual testing framework in use.
That of method getApplicationContext():
Get the application context for this test context, possibly cached.
Implementations of this method are responsible for loading the application context if the corresponding context has not already been loaded, potentially caching the context as well.
So, SpringRunner does load the context and is responsible for maintaining it. For example, if you want to persist data into an embedded database, like H2 in-memory database, you have to use SpringRunner.class; and, to clean the tables to get rid of the records you inserted after every test, you annotate the test with #DirtiesContext to tell Spring to clean it.
But, this is already an integration or component test. If your test is pure unit test, you don't have to load DB, or you just want to verify some method of a dependency is called, MockitoJUnit4Runner suffices. You just use #Mock as you like and Mockito.verify(...) and the test will pass. And it is a lot quicker.
Test should be fast. As fast as possible. So whenever possible, use MockitoJUnit4Runner to speed it up.
Scenario 2019 November : spring-boot : 2.1.1.RELEASE
You have a spring boot api rest
You need to test a service called MySuperSpringService
But, inside MySuperSpringService, are required two more autowires. One to perform a sql select (MyJpaRepository) and another to call an external api rest (MyExternalApiRest)
#Service
public class MySuperSpringService {
#Autowired
private MyRepository innerComponent1;
#Autowired
private MyExternalApiRest innerComponent2;
public SomeResponse doSomething(){}
}
How test MySuperSpringService mocking database and external api rest ?
So, in order to test this service MySuperSpringService which needs another spring beans: MyJpaRepository and MyExternalApiRest, you need to mock them using #MockBean and create the result as you need.
import static org.mockito.Mockito.when;
import java.io.IOException;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.context.junit4.SpringRunner;
import junit.framework.TestCase;
#RunWith(SpringRunner.class)
#SpringBootTest(classes = your.package.Application.class)
public class MySuperSpringServiceTest extends TestCase {
#Autowired
private MySuperSpringService serviceToTest;
#MockBean
private MyRepository myRepository;
#MockBean
private MyExternalApiRest myExternalApiRest;
#Before
public void setUp() {
Object myRepositoryResult = new Object();
//populate myRepositoryResult as you need
when(myRepository.findByClientId("test.apps.googleusercontent.com"))
.thenReturn(myRepositoryResult);
Object myExternalApiRestResult = new Object();
//populate myExternalApiRestResult as you need
when(myExternalApiRest.listUserRoles("john#doe.com")).thenReturn(myExternalApiRestResult);
}
#Test
public void testGenerateTokenByGrantTypeNoDatabaseNoGoogleNoSecurityV1(){
SomeResponse response = serviceToTest.doSomething();
//put your asserts here
}
}
you can absolutely use SpringRunner for both unit tests and integration tests.
SpringRunner Tutorial
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.
I am new to Junit testing, would like to test a private method within a class.But it causing visibility problems.how can i test a private method or protected method using Junit.Or can i test a logic within a constructor with Junit??
Simply do it like this:
private someMethod() {}
public someMethodVisibleToAll() {
someMethod();
}
It's not a good idea to hide complex logic in private methods without any access to test it, try to make methods idempotent (without side effects).
In case of legacy code use Powermock, but first try to refactor to code above, if it's not possible than you Powermock as last emergency break.
Just notice: Protected methods are testbable if you use convention that JUnit test has same package name e.g
code src/main/java
package my.package.first
in JUnit folder src/main/test
package my.package.first
than all your protected methods are available to test
Update:
There should always be a way to test private methods indirectly through public methods or protected which uses or includes using of private methods which are cases for testing. If this isn't true and you are not dependent on legacy or third party code, than it's an alert that something is wrong with class design.
I have a complex Java EE 6 app with a web module, an EJB module and some utility jars.
I want to do some integration tests with Junit. Therefore I use the openwebbeans cdi container (Thanks to Mr. Struberg http://struberg.wordpress.com/2012/03/17/controlling-cdi-containers-in-se-and-ee/)
It works perfectly. I can start a complete cdi container in a Junit test.
My problem is that I have some interceptors in my application which cannot run in a Junit test (MQ-, persistence- and transaction-interceptors). So I want to mock these interceptor implementations.
Does anybody know how to do this?
To whom it may concern ;-)
At the end I solved my issue with clean Java EE techniques. I provided a method which observes the ProcessAnnotatedType event. This method evaluates the type which is processed and if it is one of my interceptors, then I veto the processing.
public void processAnnotatedType(#Observes final ProcessAnnotatedType<?> event, final BeanManager manager) {
if (event.getAnnotatedType().getJavaClass().equals(PrivilegeCheckingInterceptor.class)) {
event.veto();
}
}
Why not just test in the container of choice with Arquillian? The other option which comes to mind would be to add in interceptors with mock functionality and exclude the actual interceptor implementation when you start the CDI container.
You can also run tests with embedded OpenEJB.
This link http://openejb.apache.org/examples-trunk/interceptors/ may be useful - perhaps setting property of 'openejb.deployments.classpath.exclude' could help.
Another option of "vetoing" could be through Deltaspike #Exclude annotation. It can veto beans based on ProjectStage.
Example:
#Exclude(ifProjectStage = ProjectStage.UnitTest.class)
public class MyInterceptor {
}
Then in your test you can activate the project stage using Deltapike test control module, example:
#RunWith(CdiTestRunner.class)
#TestControl(projectStage = UnitTest.class)
public class TestStageControl {
#Test...
}