【问题标题】:How do i create unit test for a client service with void methods?如何使用 void 方法为客户端服务创建单元测试?
【发布时间】:2021-05-18 14:19:16
【问题描述】:

我想为客户端服务创建单元测试。
客户端服务的作用是调用webservice,获取数据,按时更新数据库。
计划的方法返回 void。

如何为 a 创建单元测试

  1. 客户服务
  2. 调度方法
  3. 无效返回方法

客户端是这样的:

    @ApplicationScoped
    public class ClientClass {
    
      private static final Logger LOGGER = Logger.getLogger(VdsClient.class);
    
      @Inject
      Client client;
    
      VMR vmr;
    
      CommandService commandService;
    
      public VdsClient(VMR vmr,
          CommandService commandService) {
        this.vmr = vmr;
        this.commandService = commandService;
      }
    
      @Scheduled(XXX)
      public void getVal() {
        var monitoringStateFilter =
            new VMF.vmf(true, true);
        var monoResultList =
            vmr.fvms(monitoringStateFilter)
                                       .collectList();
        if (monoResultList != null) {
          var resultList = monoResultList.block();
          if (resultList != null) {
            resultList.stream()
                      .map(row -> row.getValue("val", val.class))
                      .map(vin -> this.updateEstimate(val.getValue()))
          }
        }
      }
      public Tuple2<String, Boolean> updateEstimate(String val) {
        List<route> routeList;
        try {
          routeList = vdsClient.getval(val)
                               .getItem();
          boolean hasDealerDestination = false;
          for (Route route : routeList) {
            if (vd.DestLocationType._00.value()
                                                .equals(route.getTransportConnectionPointTyp())) {
              hasDealerDestination = true;
              var estimate = DateTimeUtil.convertToInstantWithOffset(route.getArrivalDate(),
                  route.getArrivalTime(), route.getTimezone(), DateTimeUtil.PATTERN_LONG_DATE);
              if (estimate == null) {
                return Tuples.of(val, false);
              }
              var result = this.updateVehicleEstimate(val, estimate);
              return Tuples.of(val, result);
            }
          }
          if (!hasDealerDestination) {
            return Tuples.of(val, false);
          } else {
            return Tuples.of(val, false);
          }
        } catch (route e) {
          return Tuples.of(val, false);
        } catch (Exception e) {
          return Tuples.of(val, false);
        }
      }
    
      public Boolean updateVehicleEstimate(String val, Instant estimate) {
        var vehicleUpdate = vu.vuc.builder()
          .val(new Val(val))
          .Estimate(estimate)
          .build();
        return (Boolean) cs.ec(vu).block();
      }

【问题讨论】:

  • 单元测试实际上是为了确认在给定某些输入的情况下单元的外部影响是否按预期发生。外部影响可以是返回值和状态修改。那么,既然你调用了这个方法,你如何确保状态修改发生了呢?您需要的是一个模拟/线束来表示正在调用的外部服务,并确保某些突变按照您的预期发生或没有发生。要么模拟你的 web 服务客户端的某些部分,要么使用类似 wiremock 的东西来模拟外部 web 服务。

标签: java junit mockito junit5 quarkus


【解决方案1】:

一个单元应该只测试一个特定的代码单元是否工作正常。在您的情况下,对于单元测试,您应该假设 web 服务将返回数据并且数据库更新工作正常。我们可以通过模拟每个调用的响应来实现这一点。

对于 void 返回方法,您实际上可以验证是否确实进行了调用。

例如:

Mockito.verify(mockedObject, Mockito.times(1)).callWebService(mockedParameter1, mockedParameter2);

还有另一种方式,虽然我个人不喜欢这样: 您可以声明一个类变量,并确保无论何时调度的方法到达代码末尾,该值都会自行更新。在您的测试中读取该值并断言其值。如果值已更新,则您的代码运行良好,否则为否,则失败。

此外,如果您想真正确保 web 服务返回正确的响应/数据库条目已更新,那么这些应该是集成测试的一部分,而不是单元测试。

【讨论】:

    猜你喜欢
    • 2019-10-20
    • 2019-07-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-23
    • 1970-01-01
    相关资源
    最近更新 更多