【问题标题】:How to test Update method in Java Unit Test如何在 Java 单元测试中测试更新方法
【发布时间】:2021-11-10 13:14:34
【问题描述】:

我正在为我的 ServiceImpl 方法创建单元测试,并尝试为 update 方法创建单元测试。但是,我不确定我应该如何测试这种方法。它返回相应实体的DTO,但我真的不知道应该使用@Spy 还是@Captor。如果我设置了一个模拟变量,然后尝试检索它并更新它的值,我将需要检索相同的记录来检查它的更新值。

我是测试新手,我还没有找到合适的更新方法示例。任何帮助将不胜感激。

public CompanyDTO update(CompanyRequest companyRequest, UUID uuid) {

    final Company company = companyRepository.findByUuid(uuid)
            .orElseThrow(() -> new EntityNotFoundException(COMPANY));
    company.setName(companyRequest.getName());
    final Company savedCompany = companyRepository.save(company);
    return new CompanyDTO(savedCompany);
}

更新:最后我让它工作了,但我不确定某些部分。下面的测试方法有什么遗漏或多余的吗?

@InjectMocks
private CompanyServiceImpl companyService;

@Mock
private CompanyRepository companyRepository;

@Captor
ArgumentCaptor<Company> companyCaptorEntity;    

@Test
public void testUpdate() {
    final UUID uuid = UUID.randomUUID();
    final CompanyRequest request = new CompanyRequest();
    request.setName("Updated Company Name");

    final Company company = new Company();
    company.setName("Company Name");
    
    when(companyRepository.findByUuid(uuid))
        .thenReturn(Optional.ofNullable(company));

    //??? Do we need this?
    when(companyRepository.save(any())).thenReturn(company);

    CompanyDTO result = companyService.update(request, uuid);

    Mockito.verify(companyRepository).save(companyCaptor.capture());

    Company savedCompany = companyCaptor.getValue();
    assertEquals(request.getName(), savedCompany.getName());
}

【问题讨论】:

    标签: java unit-testing testing junit junit5


    【解决方案1】:

    update() 方法的返回类型更重要的是,我认为您应该测试传递给模拟存储库的save() 方法的实体的值(我假设您有一个)。

    为此,您可以使用ArgumentCaptor

    为了测试update() 方法的返回逻辑,您可以简单地将其在测试中的结果分配给响应对象。然后,您可以将此对象与输入对象的值进行比较。

    这是一个测试模拟存储库的保存方法的参数和更新方法的返回的示例(它们应该是两个不同的单元测试):

    @Test
    void test() {
        // Arrange
        ArgumentCaptor<Entity> entityArgumentCaptor = ArgumentCaptor.forClass(Entity.class);
        InputDto inputDto = prepareTestInput();
    
        // Act
        ResponseDto responseDto = service.update(inputDto);
        verify(repositoryMock, times(1)).save(entityArgumentCaptor.capture());
    
        // Assert
        Entity savedEntity = argumentCaptor.getValue();
        assertEquals(input.getVariable1(), savedEntity.getVariable1());
        // .....
        // compare ResponseDto and InputDto too
    }
    

    【讨论】:

    • 非常感谢您的精彩解释。您能否根据我的服务方法更新您的答案?我在某些部分遇到了一些麻烦:(
    • 我认为如果你自己尝试会更有益,因为你最终会学到很多东西。如果您有任何具体问题,请告诉我,我会提供帮助。附言请记住模拟“companyRepository.findByUuid”以返回 Company 对象。
    • 非常感谢,您能看看我的更新和测试方法吗?
    • 你做得很好。关于您的两个问题 - 不,您不需要 DTO 结果的参数捕获器,因为 update() 方法已经返回它。在给定对象不是从我们的服务方法返回而是传递给模拟类的方法的情况下,我们使用参数捕获器,因此这是我们测试它是否使用正确参数传递的一种方式。跨度>
    • 关于你关于 repository.save() 模拟的第二个问题 - 如果你不返回 Company 对象,我相信 null 将被传递给 CompanyDTO 的构造函数,在那里你可能会遇到空指针异常。大家可以自己测试看看。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-29
    • 1970-01-01
    • 1970-01-01
    • 2019-07-19
    • 2016-08-06
    相关资源
    最近更新 更多