What is mocking?
A unit test should be independent of any external resources : database, message queue etc.
Ideally, a unit test should test only one class. Mocking is a best practice when testing an object which is linked to other objects.
Example : CompanyCreateTest should only test CompanyCreate
Mockito and EasyMock:
Both are java mocking libraries for Unit Testing, and follow the same model of
- Mock external dependencies
- Setup expectations
- Run test
- Verify results
Both of the above are equivalent in features and capabilities. The essential difference exists in their usage at point 3 and 4. EasyMock needs explicit replaying and verification of Mocks and Mockito doesn't.
Similarities :
- Mocks concrete classes as well as interfaces
- Supports exact-number-of-times and at-least-once verification
- Argument matchers
- Annotation support
Remember that for Mocking, we will use mocks in our object. So, if you are using interfaces and IOC you can write your own fake implementations and inject it in your tested object. However, writing fake implementations for every linked objects could be very fastidious. That's why we will use mock libraries.
Differences between both:
Mockito has a simplified api that results in much flatter learning curve and ease of writing and maintainability. A great benefit outlined above is the developer doesn't need to call out what mocks need to be replayed. This is handled implicitly in Mockito. That compared to Easy Mock, the learning curve is higher and results in confusion several times when new mocks are added/deleted, all the explicit references need to be accordingly handled. EasyMock results in more code than Mockito to test the same functionality.
A simplified EasyMock example below :
Same example in Mockito
Using Mockito:
Definition
Mockito is a Java library used to mock objects.
Basically, you can write the following to create a fake implementation of a List :
And you can specify the expected behaviour of your mock for your test case :
MockitoJUnitRunner
Mockito comes with a JunitRunner you could enable like that :
Doing that, Mockito will create all your mocks for every objects annotated with @Mock and inject those mocks in DefaultRule that was annotated with @InjectMocks.
Inject mock without setters
The annotation @InjectMocks is very usefull when your object do not expose setter as for the object DefaultRule :
airProductManager is private and has no setters, so without the annotation @InjectMocks you would have used very tricky method to inject your mock manually.
Initialize value without setters
Sometimes, you could have some objects initialized by @Value annotation and without setters.
Exemple in TneManager :
In this situation, you have a solution using ReflectionTestUtils from Spring in your setup method :
Mock static method
Mockito is not able to mock static method by itself. However when using static method you can mix Mockito and PowerMock.
To enable PowerMock you have to use the runner PowerMockRunner.
Example in AirThirdPartyLinkImplMockitoTest :
Explanations :
Enable the runner :
Explicitely tell which object will be mocked
The following line is needed in the setup method. Otherwise every annotations Mock and InjectMock will be ignored as you don't use MockitoJUnitRunner
and the mock of the static method :
No comments:
Post a Comment