如何在 Java 的单元测试中模拟接口?

How to mock an interface in Unit Testing in Java?

我正在尝试为以下方法创建单元测试:

public List<CompanyUserDTO> findAllByUserUuidIn(final Set<UUID> userUuidList) {
        return companyUserRepository.findAllByUserUuidIn(userUuidList);
    }

这个方法returns一个列表CompanyUserDTO即接口。这是接口定义:

public interface CompanyUserDTO {
    UUID getUserUuid();

    UUID getCompanyUuid();

    String getCompanyName();

    default CompanyDTO getCompany() {
        return new CompanyDTO(getCompanyUuid(), getCompanyName());
    }
}

这里是CompanyDTO:

@Data
@AllArgsConstructor
@NoArgsConstructor
public class CompanyDTO {
    private UUID uuid;
    private String name;

    public CompanyDTO(final Company company) {
        this.uuid = company.getUuid();
        this.name = company.getName();
    }
}

我的单元测试如下图:

@Test
public void test_findAllByUserUuidIn() {
    Set<UUID> userUuidList = new HashSet<>();
    userUuidList.add(UUID.fromString("00000000-0000-0000-0000-000000000001"));
    userUuidList.add(UUID.fromString("00000000-0000-0000-0000-000000000002"));
    userUuidList.add(UUID.fromString("00000000-0000-0000-0000-000000000003"));

    // --> here I need a mock list of `CompanyUserDTO`
    List<CompanyUserDTO> companyUserDTOList = new ArrayList<>();

    when(companyUserRepository.findAllByUserUuidIn(userUuidList))
        .thenReturn(companyUserDTOList);

    List<CompanyUserDTO> result = companyUserService
        .findAllByUserUuidIn(userUuidList);

    assertEquals(companyUserDTOList, result);
}

1.那么,我应该如何在测试中创建CompanyUserDTO的模拟列表?

2.我的单元测试可以用这种方法吗?

  1. 您不需要模拟,只需自己创建对象(我猜您至少有接口的实现 CompanyUserDTO)。
  2. 其他都没问题,虽然你的方法没有那么多逻辑需要测试

鉴于您没有 CompanyUserDTO 的实现,您可以使用匿名 classes 来避免实现本身,但仅用于测试目的。您可以按如下方式进行:

@Test
public void test_findAllByUserUuidIn() {
    // Arrange
    Set<UUID> userUuidList = new HashSet<>();
    userUuidList.add(UUID.fromString("00000000-0000-0000-0000-000000000001"));
    userUuidList.add(UUID.fromString("00000000-0000-0000-0000-000000000002"));
    userUuidList.add(UUID.fromString("00000000-0000-0000-0000-000000000003"));

    CompanyUserDTO companyUserDTO = new CompanyUserDTO() {
        @Override
        public UUID getUserUuid() {
            return UUID.randomUUID();
        }
        
        @Override
        public UUID getCompanyUuid() {
            return UUID.randomUUID();
        }

        @Override
        public String getCompanyName() {
            return "Company Name Test";
        }
    };
    List<CompanyUserDTO> companyUserDTOList = new ArrayList<>();
    companyUserDTOList.add(companyUserDTO);

    when(companyUserRepository.findAllByUserUuidIn(userUuidList))
        .thenReturn(companyUserDTOList);

    // Act
    List<CompanyUserDTO> result = companyUserService
        .findAllByUserUuidIn(userUuidList);

    // Assert
    assertEquals(companyUserDTOList, result);
}

如果您希望避免匿名 classes,那么您需要在 test 源包中创建以下 class:

public class CompanyUserDTOImpl implements CompanyUserDTO {
    @Override
    public UUID getUserUuid() {
        return UUID.randomUUID();
    }
    
    @Override
    public UUID getCompanyUuid() {
        return UUID.randomUUID();
    }

    @Override
    public String getCompanyName() {
        return "Company Name Test";
    }
};

然后你的测试会更简单:

@Test
public void test_findAllByUserUuidIn() {
    // Arrange
    Set<UUID> userUuidList = new HashSet<>();
    userUuidList.add(UUID.fromString("00000000-0000-0000-0000-000000000001"));
    userUuidList.add(UUID.fromString("00000000-0000-0000-0000-000000000002"));
    userUuidList.add(UUID.fromString("00000000-0000-0000-0000-000000000003"));

    List<CompanyUserDTO> companyUserDTOList = new ArrayList<>();
    companyUserDTOList.add(new CompanyUserDTOImpl());

    when(companyUserRepository.findAllByUserUuidIn(userUuidList))
        .thenReturn(companyUserDTOList);

    // Act
    List<CompanyUserDTO> result = companyUserService
        .findAllByUserUuidIn(userUuidList);

    // Assert
    assertEquals(companyUserDTOList, result);
}