2

I want to unit test service.method(), which in its last calls dao.method (a, b) to return a list. I have successfully setup mock dao and injected into service (checked service.dao == dao).

Then I try

Mockito.when(dao.method(Mockito.any(A.class), Mockito.any(B.class)))
    .thenReturn(myList);

List aList = dao.method(new A(), new B());

List bList = service.method();

I get aList == myList as expected, but bList!= myList and always is an empty list (myList is not empty).

Is this behavior expected? If not, where I do wrong?

Service Class

@Service
public class Service{
    @Autowired
    Dao dao;

    @Transactional
    public List method() {
        ...
        A a = ...;
        B b = ...;
        return dao.method(a, b);
    }
}

Unit Test Class

@RunWith(SpringJUnit4ClassRunner.class)
public class ServiceTest {
    @Autowired
    @InjectMocks
    Service service;

    @Mock
    Dao dao;

    @Before
    public void before() {
        MockitoAnnotations.initMocks(this);
    }

    @Test
    public void testMethod() throws Exception {
        List<A> myList = Lists.newArrayList();
        myList.add(Mockito.mock(A.class));
        Mockito.when(dao.method(Mockito.any(A.class), Mockito.any(B.class))).thenReturn(myList);
        List<A> aList = dao.method(new A(), new B());
        List<A> bList  = service.method();
        List<A> cList = service.method();
        System.out.println("dao=" + (dao == service.dao)); // true
        System.out.println("aList=" + (aList == myList)); // true
        System.out.println("bList=" + (bList == myList)); // false
        System.out.println("cList=" + (bList == cList)); // false
    }
}
  • Show service definition so we can see how it interacts with the mock. – Nkosi Oct 30 '18 at 10:06
  • updated Service definition – meteoriteliu Oct 30 '18 at 10:20
  • the dao in service is not the mocked dao in test. the mocked dao needs to be explicitly injected into service – Nkosi Oct 30 '18 at 10:22
  • Show full test as a [mcve] – Nkosi Oct 30 '18 at 10:23
  • So there appears to be an issue with `@Mock`, `@InjectMocks` , and `@Autowired` in the test setup. In my answer I explicitly create and inject the mock into the subject under test, which is why it works. – Nkosi Oct 30 '18 at 11:38
  • I'm now sure it is @Transactional in Service.method that cause the problem, If remove it, everything works as expected. Any advise on how to use mockito with Transactional? – meteoriteliu Oct 31 '18 at 02:21
  • There are duplicates of this question that might give you an idea: [How to inject mock into @Service that has @Transactional](https://stackoverflow.com/questions/21124326/how-to-inject-mock-into-service-that-has-transactional) and [Transactional annotation avoids services being mocked](https://stackoverflow.com/questions/12857981/transactional-annotation-avoids-services-being-mocked) – Maik Oct 31 '18 at 02:44

0 Answers0