Java Python模拟和单元测试最佳实践

Java Python模拟和单元测试最佳实践,java,python,python-2.7,unit-testing,mocking,Java,Python,Python 2.7,Unit Testing,Mocking,我对Python世界非常陌生,并在其中学习我的方法。我有Java和C的背景,在Java/C中,单元测试方法非常清晰。我们有一个正在测试的类,我们将所有模拟的依赖项注入到测试代码中 比如: 具有服务燃油水平的车辆等级 测试用例:汽车显示低燃油指示,我们可以编写一个测试 FuelLevelService fsMock = mock(FuelLevelService .class); when(fsMock.getLevel()).thenReturn(LOW); Car ca

我对Python世界非常陌生,并在其中学习我的方法。我有Java和C的背景,在Java/C中,单元测试方法非常清晰。我们有一个正在测试的类,我们将所有模拟的依赖项注入到测试代码中

比如:

具有服务燃油水平的车辆等级 测试用例:汽车显示低燃油指示,我们可以编写一个测试

    FuelLevelService fsMock = mock(FuelLevelService .class);
    when(fsMock.getLevel()).thenReturn(LOW);
    Car car = Car(fsMock)
    car.start()
    assertTrue(car.warningIndicator());
    assertTrue(car.warning().contains("Fuel level low Warning"));
在python中,我已经读过,我们可以使用monkey补丁来设置依赖对象,并且可以进行测试

    @mock.patch('models.fuel_service.getLevel')
    def test_main(self, fuel_service):
        fuel_service.return_value = 'LOW'
        Car car = Car(fuel_service)
        car.start()
        self.assertEqual(car.warningIndicator(), True)
我打算用这种方法。但我的同事们拒绝了这个想法,并建议实例化实际对象(FuelevelService)并设置其值。我发现它非常麻烦,不需要,就像在模拟中一样,我们也可以用我们的期望做同样的事情

我目前正在努力理解我是否错了,或者在python中,我的同事认为这种方法是更好的模式

*上面我给出了一个简单的例子。在我们的项目中,创建一个实例对象并设置其值需要10-25行代码[不要问我为什么,但事实就是这样:)]来创建这个对象并设置一个值,以便它返回相同的值,这对我来说是额外的维护。对于这种创建依赖对象的方法,我们将在模块中有许多py文件

另一点是,我们这里只测试被测类(而不是依赖服务类),被测类将对依赖服务的返回值做出反应。我们可以有否定和肯定的测试来覆盖被测试的班级


对于依赖性服务类,它应该以同样的方式进行自己的测试,以验证其所有场景的可分性。所以这将是一个正在测试的类。通过这样做,我们将获得清晰的分离,并且在存在bug的地方测试将失败。

如果创建真实对象不方便/繁琐,您只需要使用mock(请参阅)

如果,正如您在问题中提到的,您可以便宜地创建真实的实例,并且可以轻松地设置其值,那么就不需要真正的模拟


此外,您不能保证模拟的行为与实际实现类似,因此您的测试可能会测试。。。但不一定是代码在生产中的实际行为。最好使用生产类。

仅当创建真实对象不方便/繁琐时,才需要使用模拟(请参见)

如果,正如您在问题中提到的,您可以便宜地创建真实的实例,并且可以轻松地设置其值,那么就不需要真正的模拟


此外,您不能保证模拟的行为与实际实现类似,因此您的测试可能会测试。。。但不一定是代码在生产中的实际行为。使用生产类更可取。

只是为了增加使用真实类实例而不是模拟的另一个原因:如果模拟测试的行为非常具体,并且更改了真实类,那么在测试模拟对象时可能会遗漏一些意外的内容,即使您在第一次设置测试时做得很彻底。如果你不需要的话,没有理由冒险。我已经更新了这个问题。请看。实际上,在我们的例子中,创建真实对象是一个很长的过程(上面是一个简单的例子),我们必须创建新的单独的py文件来创建这个真实对象。在我看来,这是额外的努力。如果我们只需要一个返回简单值的方法(为什么要编写一个包含10-25行代码的新方法)。请记住,我们测试的是测试中的类,而不是这个依赖项。对于此依赖项服务,我们应该有单独的测试。只需添加使用真实类实例而不是模拟的另一个原因:如果您的模拟测试非常特定的行为,并且您更改了真实类,那么在测试模拟对象时,您可能会错过一些意外的内容,即使您在第一次设置测试时非常彻底。如果你不需要的话,没有理由冒险。我已经更新了这个问题。请看。实际上,在我们的例子中,创建真实对象是一个很长的过程(上面是一个简单的例子),我们必须创建新的单独的py文件来创建这个真实对象。在我看来,这是额外的努力。如果我们只需要一个返回简单值的方法(为什么要编写一个包含10-25行代码的新方法)。请记住,我们测试的是测试中的类,而不是这个依赖项。对于这个依赖项服务,我们应该有单独的测试。