如何使用junit 5和mockito测试update方法,并在服务层进行异常处理

jdgnovmf  于 9个月前  发布在  其他
关注(0)|答案(2)|浏览(106)

我从Mockito开始做单元测试。我已经看到了几个如何执行单元测试的例子,但它对我不起作用,因为当我传递对象来搜索它是否存在并修改它时,异常被抛出,测试被中断。
当这一行被执行时:BDDMockito.given(syndromeTypeServiceMock.modifySyndromeType(synTypeMock)).willReturn(synTypeMockAspect);它在服务中输入方法,当使用mock进行验证时,通过不去数据库查找记录,它返回null或空,并且下面的验证引发异常。我如何用Mockito验证这个异常,使它通过测试?
先谢了!

@ExtendWith(MockitoExtension.class)
public class SyndromeTypeServiceTest {

    Logger LOGGER = LoggerFactory.getLogger(getClass());
    
    @Mock
    SyndromeTypeRepository syndromeTypeRepository;
    @Mock
    SyndromeTypeTransRepository syndromeTypeTransRepository;
    @InjectMocks
    SyndromeTypeServiceImpl syndromeTypeServiceMock;
    
    @Test
    public void test_modify_SyndromeType_when_synTransId_exist() throws PersistenceException {
        LOGGER.info("test_modify_SyndromeType_when_synTransId_exist >>");
        

        SyndromeType synTypeMock = SyndromeType.builder()
                                                .synTypeId(10)
                                                .synTypeName("Musculoesquelético.")
                                                .lanCode("es")
                                                .synTypeTransId(10)
                                                .build();
        
        SyndromeType synTypeMockEspect = SyndromeType.builder()
                                                .synTypeId(10)
                                                .synTypeName("Musculoesquelético.")
                                                .lanCode("es")
                                                .synTypeTransId(10)
                                                .build();

        BDDMockito.given(syndromeTypeServiceMock.modifySyndromeType(synTypeMock)).willReturn(synTypeMockEspect);

        assertEquals(synTypeMock.getSynTypeTransId(), synTypeMockEspect.getSynTypeTransId());
        assertEquals(synTypeMock.getSynTypeId(), synTypeMockEspect.getSynTypeId());
        assertEquals(synTypeMock.getSynTypeName(), synTypeMockEspect.getSynTypeName());

        LOGGER.info("<< test_modify_SyndromeType_when_synTransId_exist");
        
    }
    
}

服务层

@Service
@Transactional
public class SyndromeTypeServiceImpl implements SyndromeTypeService {

    Logger LOGGER = LoggerFactory.getLogger(getClass());
    
    final SyndromeTypeRepository syndromeTypeRepository;
    final SyndromeTypeTransRepository syndromeTypeTransRepository;
    
    public SyndromeTypeServiceImpl(SyndromeTypeRepository syndromeTypeRepository,
            SyndromeTypeTransRepository syndromeTypeTransRepository) {
        this.syndromeTypeRepository = syndromeTypeRepository;
        this.syndromeTypeTransRepository = syndromeTypeTransRepository;
    }

    @Override
    public List<SyndromeType> renderSyndromeTypes(List<SyndromeTypeTransEntity> synTypesEtts){
        LOGGER.info("Rendering SyndromeTypeEntity results");
        List<SyndromeType> synTypes = new ArrayList<SyndromeType>(0);

        if(null != synTypesEtts) {
            synTypesEtts.stream()
                .forEach(
                    s -> {
                            synTypes.add(
                                    SyndromeType.builder()
                                                .synTypeId(s.getSynTypeEtt().getSynTypeId())
                                                .synTypeName(s.getSynTypeName())
                                                .lanCode(s.getLanCodeEtt().getLanCode())
                                                .synTypeTransId(s.getSynTypeTransId())
                                                .build()
                                    );
                });
            
        }
        
        return synTypes;
    }

    @Override
    public SyndromeType modifySyndromeType(SyndromeType synType) throws PersistenceException {
        LOGGER.info("modifySyndromeType >>");
        
        Optional<SyndromeTypeTransEntity> synTypeEtt = java.util.Optional.empty();
        
        if(null != synType.getSynTypeTransId()) {
            synTypeEtt = syndromeTypeTransRepository.findById(synType.getSynTypeTransId()); 
        }

        if(!synTypeEtt.isPresent() || synTypeEtt.isEmpty()) {
            throw new PersistenceException(ErrorMessage.RECORD_NOT_EXIST.name());
        }
        
        SyndromeTypeTransEntity synTypeTrans = SyndromeTypeTransEntity.builder()
                                                        .lanCodeEtt(LanguageEntity.builder()
                                                                         .lanCode(synType.getLanCode())
                                                                         .build())
                                                        .synTypeName(synType.getSynTypeName())
                                                        .build();
        
        synTypeTrans = syndromeTypeTransRepository.save(synTypeTrans);
        
        List<SyndromeType> synTypesTO = this.renderSyndromeTypes(List.of(synTypeTrans));
        
        SyndromeType synTypeTO = synTypesTO.isEmpty() ? null : synTypesTO.get(0);
        
        LOGGER.info("<< modifySyndromeType");
        return synTypeTO;
    }
}
dgiusagp

dgiusagp1#

Mockito mock对象(使用Mockito.mock@Mock创建)默认情况下总是返回null或空集合。如果你要求它们返回一个不同的值,你必须存根的方法。
另一方面,@InjectMocks创建接口/类的 * 真实的 * 示例,并将模拟对象作为依赖项注入。一个真实的示例的方法不能被stub--而且这也没有意义,因为这是您通常希望在测试中使用的类。
这意味着如果您想测试您的服务,您需要确保您调用的是真实的服务,并且它调用的任何方法都返回有用的值。
下面的代码块在 repository(不是服务)上调用findById,您已经为它创建了一个mock对象,但从未存根任何方法。

if(null != synType.getSynTypeTransId()) {
   synTypeEtt = syndromeTypeTransRepository.findById(synType.getSynTypeTransId()); 
}

仓库的方法可以在你的测试中被存根化如下:

when(syndromeTypeTransRepository.findById(10)) // the id passed to the service
    .thenReturn(Optional.of(...)); // a value that makes sense for your test

第二次对仓库的调用也必须被存根化:

synTypeTrans = syndromeTypeTransRepository.save(synTypeTrans);

一个足够的存根实现可能只是返回参数本身:

when(syndromeTypeTransRepository.save(any()))
    .thenReturn(AdditionalAnswers.returnsFirstArg());

在测试方法中设置了存根调用之后,必须调用类的 * 真实的 * 方法(如果不调用真实的方法,那么测试的是什么!?)

final SyndromeType actualType = syndromeTypeServiceMock.modifySyndromeType(synType);

然后Assert返回的正确值:

assertEquals(expectedType, actualType); // if SynType implement equals()

// without equals() properties need to be compared manually
assertEquals(10, actualType.getSynTypeTransId());
assertEquals(10, actualType.getSynTypeId());
assertEquals("Musculoesquelético.", actualType.getSynTypeName());
khbbv19g

khbbv19g2#

感谢@knittle,他已经能够纠正测试,最重要的是,对于要测试的方法中的每个动作,必须执行模拟。这是对测试的修改。

@Test
public void test_modify_SyndromeType_when_synTransId_exist() throws PersistenceException {
    LOGGER.info("test_modify_SyndromeType_when_synTransId_exist >>");
    
    SyndromeTypeTransEntity synTypeTrans = SyndromeTypeTransEntity.builder()
                                                        .synTypeTransId(10)
                                                        .synTypeName("Musculoesquelético.")
                                                        .lanCodeEtt(LanguageEntity.builder()
                                                                         .lanCode("es")
                                                                         .lanName("Español")
                                                                         .build())
                                                        .synTypeEtt(SyndromeTypeEntity.builder().synTypeId(10).build())
                                                        .build();
    
    
    when(syndromeTypeTransRepository.findById(10)) // the id passed to the service
                                    .thenReturn(Optional.of(synTypeTrans)); // a value that makes sense for your test
    
    when(syndromeTypeTransRepository.save(any())) 
                                    .thenReturn(synTypeTrans); 

    SyndromeType synType = SyndromeType.builder()
                                            .synTypeId(10)
                                            .synTypeName("Musculoesquelético.")
                                            .lanCode("es")
                                            .synTypeTransId(10)
                                            .build();

    final SyndromeType actualSynType = syndromeTypeService.modifySyndromeType(synType);

    assertEquals(10, actualSynType.getSynTypeTransId());
    assertEquals(10, actualSynType.getSynTypeId());
    assertEquals("Musculoesquelético.", actualSynType.getSynTypeName());

    LOGGER.info("<< test_modify_SyndromeType_when_synTransId_exist");
    
}

相关问题