I'm currently studying the Mockito framework and I've created several test cases using Mockito. But then I read that instead of invoking mock(SomeClass.class) I can use the @Mock
and the @InjectMocks
- The only thing I need to do is to annotate my test class with @RunWith(MockitoJUnitRunner.class)
or use the MockitoAnnotations.initMocks(this);
in the @Before
method.
But it doesn't work - It seems that the @Mock
won't work! Here is my 2 codes revisions - one using the annotations and one without.
What am I doing wrong?
public class ReportServiceImplTestMockito { private TaskService mockTaskService; // This is the Mock object private ReportServiceImpl service; @Before public void init(){ service = new ReportServiceImpl(); mockTaskService = mock(TaskServiceImpl.class); service.setTaskServiceImpl(mockTaskService); } /// ... Some tests }
As I said - this work great. But the following wont:
@RunWith(MockitoJUnitRunner.class) public class ReportServiceImplTestMockito { @Mock private TaskService mockTaskService; @InjectMocks private ReportServiceImpl service; // Some tests }
And here is the ReportServiceImpl
class:
@Service public class ReportServiceImpl implements ReportService { @Autowired private TaskService taskServiceImpl; public ReportServiceImpl(){} public ReportServiceImpl(TaskService taskService){ this.taskServiceImpl = taskService; } public void setTaskServiceImpl(TaskService taskServiceImpl) { this.taskServiceImpl = taskServiceImpl; } }
What am I missing?
A mock doesn't have any real implementation. @InjectMocks would try to find and call setters for whatever mock objects have already been created and pass them in.
@Mock: It is used to mock the objects that helps in minimizing the repetitive mock objects. It makes the test code and verification error easier to read as parameter names (field names) are used to identify the mocks. The @Mock annotation is available in the org. mockito package.
@InjectMocks is the Mockito Annotation. It allows you to mark a field on which an injection is to be performed. Injection allows you to, Enable shorthand mock and spy injections.
We can use the @MockBean to add mock objects to the Spring application context. The mock will replace any existing bean of the same type in the application context. If no bean of the same type is defined, a new one will be added.
O.K, I got my mistake!!! I've used the @InjectMocks
but initialized the same variable in the init() method... So what happened was that mockito injected the mock objects to my variable - but seconds later I ran it over - initializing that very same variable!!!
Your code works fine for me using Mockito 1.9.
Using an 1.8+ version of Mockito I get a very specific error message telling me exactly how to fix the problem. As php-coder suggests: For Mockito 1.8+ you need to initialize the field.
Did you see this or any other error message?
Edit:
The following code works for me. Small changes:
TaskService
System.out.println
Does it produce an error for you? :
Service:
public class ReportServiceImpl { private TaskService taskServiceImpl; public ReportServiceImpl() { } public ReportServiceImpl(TaskService taskService) { this.taskServiceImpl = taskService; } public void setTaskServiceImpl(TaskService taskServiceImpl) { this.taskServiceImpl = taskServiceImpl; } public TaskService getTaskServiceImpl() { return taskServiceImpl; } }
Dependency:
public class TaskService { }
Test, prints mockTaskService
:
@RunWith(MockitoJUnitRunner.class) public class ReportServiceImplTestMockito { @Mock private TaskService mockTaskService; @InjectMocks private ReportServiceImpl service; @Test public void testMockInjected() { System.out.println(service.getTaskServiceImpl()); } }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With