I began to learn about Mokito only today. I wrote some simple tests (with JUnit, see below), but I cannot figure out how I can use the mock object inside Spring controls beans. Which is best for working with Spring. How should I mislead addiction to my bean?
You can skip this up to back to my question .
First of all, what I found out. This is a very good article by Mocks Are not Stubs that explains the basics (Mock checks for validation checking ). Then there is a good example of Mockito. Here It is easier to mock with mockito . We have an explanation that Mockito mock objects are both mock-ups and stubs.
Here Mockito and here Matchers you can find more examples.
This test
@Test public void testReal(){ List<String> mockedList = mock(List.class); //stubbing //when(mockedList.get(0)).thenReturn("first"); mockedList.get(anyInt()); OngoingStubbing<String> stub= when(null); stub.thenReturn("first"); //String res = mockedList.get(0); //System.out.println(res); //you can also verify using argument matcher //verify(mockedList).get(anyInt()); verify(mockedList); mockedList.get(anyInt()); }
works great.
Back to my question. Here Mockito Injection mocks Spring bean , someone tries to use Springs ReflectionTestUtils.setField() , but here Spring Integration tests, creating Mock Objects , we recommend changing the Spring context.
I did not quite understand the last two links ... Can someone explain to me what the problem is with Spring with Mockito? What is wrong with this decision?
@InjectMocks private MyTestObject testObject @Mock private MyDependentObject mockedObject @Before public void setup() { MockitoAnnotations.initMocks(this); }
stack overflow
EDIT : I was not entirely clear. I will give 3 code examples to clarify myself: Suppose we have a HelloWorld bean with the printHello() method and a HelloFacade bean with the sayHello method that redirects the HelloWorld printHello() method.
The first example uses the Spring context without a special runner, using ReflectionTestUtils to inject dependencies (DI):
public class Hello1Test { private ApplicationContext ctx; @Before public void setUp() { MockitoAnnotations.initMocks(this); this.ctx = new ClassPathXmlApplicationContext("META-INF/spring/ServicesImplContext.xml"); } @Test public void testHelloFacade() { HelloFacade obj = (HelloFacade) ctx.getBean(HelloFacadeImpl.class); HelloWorld mock = mock(HelloWorld.class); doNothing().when(mock).printHello(); ReflectionTestUtils.setField(obj, "hello", mock); obj.sayHello(); verify(mock, times(1)).printHello(); } }
As @Noam pointed out that there is a way to start it with an explicit call to MockitoAnnotations.initMocks(this); . I will also stop using Spring context in this example.
@RunWith(MockitoJUnitRunner.class) public class Hello1aTest { @InjectMocks private HelloFacade obj = new HelloFacadeImpl(); @Mock private HelloWorld mock; @Test public void testHelloFacade() { doNothing().when(mock).printHello(); obj.sayHello(); } }
Another way to do it
public class Hello1aTest { @Before public void setUp() { MockitoAnnotations.initMocks(this); } @InjectMocks private HelloFacadeImpl obj; @Mock private HelloWorld mock; @Test public void testHelloFacade() { doNothing().when(mock).printHello(); obj.sayHello(); } }
Noth that in the previous example we need to manually install HelloFacadeImpl and assign it HelloFacade, beacuse HelloFacade is the interface. In the last example, we can simply declare HelloFacadeImpl, and Mokito will create it for us. The disadvantage of this approach is that now a single test refers to the impl class rather than the interface.