Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/383.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java “单元测试”;胶水“;代码或没有任何实际逻辑的代码_Java_Unit Testing - Fatal编程技术网

Java “单元测试”;胶水“;代码或没有任何实际逻辑的代码

Java “单元测试”;胶水“;代码或没有任何实际逻辑的代码,java,unit-testing,Java,Unit Testing,我的问题将出现在一个简化的示例(Java)中: 你会如何进行这个类的单元测试? 我对此思考了一会儿,并确定了几个选项: 在不模仿制造商的情况下,对退回的车辆进行测试 从接口的角度来看,这是最好的选择,但它不会是对VehiclerDepository的单独单元测试。我看不出与VehicleBuilder一起测试VehiclerDepository相比,只测试VehicleBuilder有什么真正的优势。VehicleBuilder也可能具有复杂的逻辑(例如检查存在哪些附件),这会导致多个执行路径,

我的问题将出现在一个简化的示例(Java)中:

你会如何进行这个类的单元测试? 我对此思考了一会儿,并确定了几个选项:

在不模仿制造商的情况下,对退回的车辆进行测试
从接口的角度来看,这是最好的选择,但它不会是对VehiclerDepository的单独单元测试。我看不出与VehicleBuilder一起测试VehiclerDepository相比,只测试VehicleBuilder有什么真正的优势。VehicleBuilder也可能具有复杂的逻辑(例如检查存在哪些附件),这会导致多个执行路径,这会使VehicleRepository的测试非常复杂

重构代码以测试生成器的状态
例如,将getLuxuryCar操作拆分为两个操作:

public Vehicle getLuxuryCar() {
  VehicleBuilder builder = getLuxuryCarBuilder();
  return builder.build();
}

// Visible for testing in the same package
protected VehicleBuilder getLuxuryCarBuilder() {
  VehicleBuilder builder = getVehicleBuilder();
  builder.setChassis(chassisDAO.findBySize(ChassisSize.NORMAL));
  builder.setEngine(engineDAO.findByPower(EnginePower.HIGH));
  builder.setWheelTemplate(wheelDAO.findBySize(WheelSize.NORMAL));
  builder.addAccessory(accessoryDAO.findByType(Accessory.LUXURY));
  return builder;
}
与行为测试相比,我更喜欢状态测试,而且测试可能更有弹性,但我不太喜欢结果代码(尤其是getLuxuryCar()方法,它实际上什么都不做)

模拟车辆制造商并测试其行为
我相信这样的单元测试只是被测试的实际操作的复制品,不会增加任何真正的好处。它也会非常脆弱,完全依赖于被测试操作的内部。可能的单元测试(使用JMock)如下:

@Test
public void shouldBuildLuxuryCar() {
  context.checking(new Expectations() {{
    oneOf(chassisDAOmock).findBySize(ChassisSize.NORMAL);
    oneOf(vehicleBuilderMock).setChassis(with(any(Chassis.class)));

    oneOf(engineDAOmock).findByPower(EnginePower.HIGH);
    oneOf(vehicleBuilderMock).setEngine(with(any(Engine.class)));

    oneOf(wheelDAOmock).findBySize(WheelSize.NORMAL));
    oneOf(vehicleBuilderMock).setWheelTemplate(with(any(Wheel.class)));

    oneOf(accessoryDAOmock).findByType(Accessory.LUXURY));
    oneOf(vehicleBuilderMock).setAccessories(with(any(Set.class)));

    oneOf(vehicleBuilderMock).build();
  }});

  context.assertIsSatisfied();
}
不要对其进行单元测试

我倾向于这个选项,因为我对任何替代方案都不满意,而且操作似乎并不需要任何测试。为了澄清,我仍将单独对VehicleBuilder进行单元测试,但不会对VehicleRepository进行单元测试。然而,这似乎不是主流观点,例如,从这个问题可以看出:

我认为你的观点都有价值,这只是我将要做的建议

集成测试更适合此代码,使用生成模拟数据或具有测试数据源的注入DAO对象

但是,您的问题是针对单元测试的,在这种情况下,我认为针对返回的车辆对象进行测试(不模仿构建者)是最佳选择。为了避免复杂性,我将对返回的车辆进行简单的测试(检查它是否为null,也许是它的“类不变量”),而不是车辆类型的详细信息(该测试留给车辆的制造商/制造商)

该测试的优点是:

  • 如果车辆/建造商后来扩展到需要附加属性(例如,所有车辆都应该有制动器),但开发人员忽略了更新存储库,则测试将失败
  • 它将充当一个健全的测试,至少确保代码能够毫无例外地执行

  • 我同意@Aegis。你的代码看起来很简单,所以我认为所有的模拟代码都是多余的。我喜欢集成测试,因为它们更容易编写,并且提供了良好的代码覆盖率。为复杂类编写单元测试。当被测试的代码可以执行多个可选流时,将其与代码的其余部分隔离测试就更容易了。我还认为针对返回的vehicle对象进行测试(无需模拟构建器)是一个不错的选择。然而,我并不完全同意@Aegis列出的优势。首先,为了简单起见,我更喜欢这种方法。
    @Test
    public void shouldBuildLuxuryCar() {
      context.checking(new Expectations() {{
        oneOf(chassisDAOmock).findBySize(ChassisSize.NORMAL);
        oneOf(vehicleBuilderMock).setChassis(with(any(Chassis.class)));
    
        oneOf(engineDAOmock).findByPower(EnginePower.HIGH);
        oneOf(vehicleBuilderMock).setEngine(with(any(Engine.class)));
    
        oneOf(wheelDAOmock).findBySize(WheelSize.NORMAL));
        oneOf(vehicleBuilderMock).setWheelTemplate(with(any(Wheel.class)));
    
        oneOf(accessoryDAOmock).findByType(Accessory.LUXURY));
        oneOf(vehicleBuilderMock).setAccessories(with(any(Set.class)));
    
        oneOf(vehicleBuilderMock).build();
      }});
    
      context.assertIsSatisfied();
    }