Mockito:验证是否调用了Spring Data JPA delete()方法

Dom*_*nik 1 unit-testing spring-mvc mockito spring-data-jpa

所以,我对单元测试相对较新,特别是mockito,我试图弄清楚如何在Spring WebMVC中测试以下场景:

这是我的服务类(简化):

@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();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这里我称之为Spring Data JPA crudrepository的"内置"delete方法,这意味着存储库本身没有自定义实现(使用OpenJPA).

这是我简化的测试类:

@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);
    }
    //...
}
Run Code Online (Sandbox Code Playgroud)

所以,我尝试验证删除是否被调用testRemoveSomething(),但我得到以下输出:

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

而且我几乎没有想法为什么,说实话(考虑一下@Transactional,或许?但这并没有让我得到解决方案,但是).可能是我在这里完全错了(建筑,dunno) - 如果是这样,请随时给我一个提示:)

在这里获得一些帮助会很棒!提前致谢.

JB *_*zet 5

你的方法会调用findOne(),检查是否返回了什么,然后调用delete().所以你的测试应该首先确保findOne返回一些东西.否则,模拟存储库的findOne()方法默认返回null.此外,您应该验证调用在执行后是否已执行.不是之前.

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

    myService.removeTableEntry(0l, USERID);

    verify(myCrudRepository, times(1)).delete(0L);
}
Run Code Online (Sandbox Code Playgroud)

此外,您应该使用@InjectMocks注释而不是实例化您的服务并使用反射注入存储库.