【问题标题】:Using Mockito to mock out Spring Boot repository delete call throws java.util.NoSuchElementException on get()使用 Mockito 模拟 Spring Boot 存储库删除调用在 get() 上抛出 java.util.NoSuchElementException
【发布时间】:2018-11-21 09:00:38
【问题描述】:

我是 Spring Boot 和 Mockito 的新手,在我的服务测试中模拟存储库调用时遇到问题。

我有一个“删除”服务方法调用,如下所示,我试图通过模拟存储库调用来使用 Mockito 进行测试:

public interface IEntityTypeService {
    public EntityType getById(long id);
    public EntityType getByName(String name);
    public List<EntityType> getAll();
    public void update(EntityType entityType);
    public void delete(long id);
    public boolean add(EntityType entityType);
}

@Service
public class EntityTypeServiceImpl implements IEntityTypeService {
    @Autowired
    private EntityTypeRepository entityTypeRepository;

    @Override
    public void delete(long id) {
        entityTypeRepository.delete(getById(id));   
    }

    @Override
    public EntityType getById(long id) {
        return entityTypeRepository.findById(id).get();
    }

....implementation of other methods from the interface
}

我的存储库如下所示:

@RepositoryRestResource
public interface EntityTypeRepository extends LookupObjectRepository<EntityType> {

}

我没有在存储库中实现任何方法,因为我让 Spring Boot 为我连接它。

我的测试如下:

@RunWith(SpringRunner.class)
public class EntityTypeServiceTest {
    @TestConfiguration
    static class EntityTypeServiceImplTestContextConfiguration {

        @Bean
        public IEntityTypeService entityTypeService() {
            return new EntityTypeServiceImpl();
        }
    }

    @Autowired
    private IEntityTypeService entityTypeService;
    @MockBean
    private EntityTypeRepository entityTypeRepository;

    @Test
    public void whenDelete_thenObjectShouldBeDeleted() {                
        final EntityType entity = new EntityType(1L, "new OET");
        Mockito.when(entityTypeRepository.findById(1L).get()).thenReturn(entity).thenReturn(null);

        // when
        entityTypeService.delete(entity.getID());

        // then
        Mockito.verify(entityTypeRepository, times(1)).delete(entity);
        assertThat(entityTypeRepository.findById(1L).get()).isNull();       
    }
}

当我运行测试时,我收到一条错误消息“java.util.NoSuchElementException: No value present”

java.util.NoSuchElementException: No value present
    at java.util.Optional.get(Optional.java:135)
    at xyz.unittests.service.EntityTypeServiceTest.whenDelete_thenObjectShouldBeDeleted(OriginatingEntityTypeServiceTest.java:41)

它引用了测试中的行Mockito.when(originatingEntityTypeRepository.findById(1L).get()).thenReturn(entity).thenReturn(null);

我认为我必须模拟该调用的原因是因为 Service 中的 delete 方法调用了同一服务中的 getById() 方法,而后者又调用了 entityTypeRepository.findById(id).get()

就是这样,我假设我必须模拟删除。但很明显我错了。任何帮助将不胜感激。

非常感谢

【问题讨论】:

  • 好吧 entityTypeRepository.findById(1L) 还没有被模拟,我们在上面调用了 get()。

标签: spring-boot mockito


【解决方案1】:
@Test
public void whenDelete_thenObjectShouldBeDeleted() {                
    final EntityType entity = new EntityType(1L, "new OET");
    Optional<EntityType> optionalEntityType = Optional.of(entity);
     Mockito.when(entityTypeRepository.findById(1L)).thenReturn(optionalEntityType);

    // when
    entityTypeService.delete(entity.getID());

    // then
    Mockito.verify(entityTypeRepository, times(1)).delete(entity);
    //I dont think you need to assert to confirm actual delete as you are testing mock registry. to assert somethink like below you need to return null by mocking the same call again and return the null but thats of no use
    //assertThat(entityTypeRepository.findById(1L).get()).isNull();       
 }

更新了您的测试。基本上我们首先需要模拟 findById 的结果。请参阅我上面断言实际删除的评论。

【讨论】:

  • 谢谢bittu。非常感激。关于您关于不需要断言的评论。这是有道理的,但如果我删除它,我所测试的只是删除方法被调用一次。似乎真的是一个太基本的测试。但也许这就是我需要做的所有事情,因为存储库测试应该是它实际上从数据库中删除的一项测试。我只是在这里测试我的逻辑。
  • 在一个相关但不同的说明上,虽然我引起了您(或其他任何人)的注意,但您是否知道我可以从 Github 中提取一个很好的示例项目,该项目使用 Spring Boot 和正常层(域、存储库、服务、控制器)并通过模拟进行测试(单元和集成)?我觉得这是我们都遇到的事情,如果有一个“模板”可以向别人学习,那会很棒吗?当然我的用例是不同的,但模式会适用。
猜你喜欢
  • 2022-12-11
  • 1970-01-01
  • 1970-01-01
  • 2018-11-24
  • 2015-12-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-26
相关资源
最近更新 更多