Python Django测试-所有测试中的补丁对象
我需要为我的测试创建某种类型的Python Django测试-所有测试中的补丁对象,python,django,unit-testing,django-testing,python-mock,Python,Django,Unit Testing,Django Testing,Python Mock,我需要为我的测试创建某种类型的MockMixin。它应该包括所有调用外部源的模拟。 例如,每次我在管理面板中保存模型时,我都会调用一些远程URL。这将是很好的,有嘲笑和使用这样: class ExampleTestCase(MockedTestCase): # tests 所以每次我在admin中保存模型时,例如在功能测试中,都会应用这个模拟,而不是调用远程URL 这真的有可能吗?我能在一个特定的测试中做到这一点,这不是问题。但是,有一些全局模拟会更有用,因为我经常使用它。根据: 补丁
MockMixin
。它应该包括所有调用外部源的模拟。
例如,每次我在管理面板中保存模型时,我都会调用一些远程URL。这将是很好的,有嘲笑和使用这样:
class ExampleTestCase(MockedTestCase):
# tests
所以每次我在admin中保存模型时,例如在功能测试中,都会应用这个模拟,而不是调用远程URL
这真的有可能吗?我能在一个特定的测试中做到这一点,这不是问题。但是,有一些全局模拟会更有用,因为我经常使用它。根据:
补丁可以用作TestCase类装饰器。它的工作原理是
修饰类中的每个测试方法。这减少了样板文件
当您的测试方法共享公共补丁集时编写代码
这基本上意味着您可以创建一个应用了@patch
decorator的基本测试类,该类将模拟外部调用,而内部的每个测试方法都将被执行
此外,您还可以分别在setUp()
和tearDown()
方法中使用patcher的方法:
class BaseTestCase(TestCase):
def setUp(self):
self.patcher = patch('mymodule.foo')
self.mock_foo = self.patcher.start()
def tearDown(self):
self.patcher.stop()
如果您使用的是teardown()
,那么
您必须通过调用stop
确保修补“撤消”。这可能比您想象的更加烦躁,因为如果在设置中引发异常
,则不会调用拆卸
如果测试中出现异常,则修补不会撤消。更好的方法是在设置()中调用。然后您可以完全省略tearDown()
方法
class BaseTestCase(TestCase):
def setUp(self):
self.patcher = patch('mymodule.foo')
self.mock_foo = self.patcher.start()
self.addCleanup(self.patcher.stop) # add this line
我最终创造了一个测试跑步者来达到我的目的。我需要模拟文件存储,以便在测试时图像不会实际写入文件系统。images对象在许多测试中都被调用,因此修补每个类将不会DRY
。此外,我注意到,如果测试失败,模拟文件本身会将其留在系统上。但这种方法没有
我在项目根目录中创建了一个文件runner.py
#runner.py
从unittest.mock导入修补程序
从django.test.runner导入DiscoveryRunner
从myapp.Factorys导入ImageFactory
类UnitTestRunner(DiscoveryRunner):
@修补程序('django.core.files.storage.FileSystemStorage.save')
def运行测试(自我、测试标签、模拟保存、额外测试=无,**kwargs):
mock_save.return_value=ImageFactory.get_image()
return super().运行测试(测试标签,额外测试=None,**kwargs)
然后,我将使用python manage.py测试运行测试--testrunner=runner.UnitTestRunner
为了清晰起见,ImageFactory.get\u image
方法是一种自定义方法
从django.core.files.base导入内容文件
从factory.django导入DjangoModelFactory
从io导入字节io
从PIL将图像导入为PIL图像
从随机导入randint
类ImageFactory(DjangoModelFactory):
@类方法
def get_图像(cls,name='trial',extension='png',size=None):
如果大小为“无”:
宽度=randint(20,1000)
高度=randint(20,1000)
大小=(宽度、高度)
颜色=(256,0,0)
file_obj=BytesIO()
image=pilmimage.new(“RGBA”,size=size,color=color)
image.save(文件\对象,扩展名)
文件_obj.seek(0)
返回ContentFile(file_obj.read(),f'{name}.{extension}')
这也意味着我必须装饰我的每个测试用例,而不是Mixin
测试类。我不得不为每个测试方法添加额外的参数,这也很不方便。但总比什么都没有好。@galozek请看相关主题:和。第二个解决方案奏效了。我尝试了这种方法,但缺少start()
/stop()
部分。谢谢。请注意,您最好使用self.addCleanup(self.patcher.stop)
而不是在tearDown
中执行此操作,因为无论是否存在异常,清理都会运行。请参阅@Meistro的答案。不要忘记包括导入:来自unittest导入测试用例
,来自导入unittest。模拟导入补丁
将始终被调用,即使您的测试引发异常。从文档中可以看到:“如果安装()失败,意味着拆卸()因此,调用addCleanup
比希望在设置中不出现异常要好。不要忘记包括导入:来自unittest导入TestCase
,来自import unittest.mock导入补丁
wrt@Meistro上面提到的内容。。。确保尽快在设置
方法中添加清理钩子,否则,如果在添加钩子之前失败,它将无效