Question

So, I am relatively new to unit-testing and especially mockito and am trying to figure out how to test the following scenario in Spring WebMVC:

This is my Service Class (simplified):

@Service
public class MyServiceImpl implements MyService {

    @Resource
    private MyCrudRepository myCrudRepository;


    /**
     * Method to delete(!) an entry from myTable.
     *
     */
    @Transactional
    public void removeTableEntry(Long entryOid, String userId) throws Exception {

        if (myCrudRepository.findOne(entryOid) != null) {
            myCrudRepository.delete(entryOid);
            log.info("User ID: " + userId + " deleted Entry from myTable with Oid " + entryOid + ".");
        } else {
            log.error("Error while deleting Entry with Oid: "+ entryOid + " from User with ID: " + userId);
            throw new Exception();
        }
    }
}

Here I call the "built-in" delete-method of Spring Data JPA crudrepository, meaning no custom implementation in the repository itself (Using OpenJPA).

This is my simplified Test-Class:

@RunWith(MockitoJUnitRunner.class)
public class MyServiceImplTest {

    final String USERID = "Testuser";

    MyServiceImpl myService;

    @Mock
    MyCrudRepository myCrudRepository;


    @Before
    public void setUp() {
        myService  = new MyServiceImpl();
        ReflectionTestUtils.setField(myService, "myCrudRepository", myCrudRepository);
    }

    //works (as expected? not sure)
    @Test(expected = Exception.class)
    public void testRemoveSomethingThrowsException() throws Exception {
        doThrow(Exception.class).when(myCrudRepository).delete(anyLong());
        myService.removeSomething(0l, USERID);
    }

    //does not work, see output below
    @Test
    public void testRemoveSomething() throws Exception {
        verify(myCrudRepository, times(1)).delete(anyLong());
        myService.removeSomething(0l, USERID);
    }
    //...
}

So, I try to verify that delete is called in testRemoveSomething(), but instead I get the following output:

Wanted but not invoked:
myCrudRepository.delete(<any>);
-> at myPackage.testRemoveSomething(MyServiceImplTest.java:98)
Actually, there were zero interactions with this mock.

And I'm nearly out of ideas why, to be honest (thinking about the @Transactional, perhaps? But this didn't get me to the solution, yet). May be that I'm completely wrong here (architectural, dunno) - if so, please feel free to give me a hint :)

It would be great to get some help here! Thanks in advance.

Était-ce utile?

La solution

Your method fist calls findOne(), check if that returns something, and then calls delete(). So your test should first make sure that findOne returns something. Otherwise, the mock repository's findOne() method returns null by default. Moreover, you should verify that the call has been executed after it has been executed. Not before.

@Test
public void testRemoveSomething() throws Exception {
    when(myCrudRepository.findOne(0L)).thenReturn(new TableEntry());

    myService.removeTableEntry(0l, USERID);

    verify(myCrudRepository, times(1)).delete(0L);
}

Also, you should use the @InjectMocks annotation rather than instantiating your service and injecting the repository using reflection.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top