Skip to main content
 首页 » 编程设计

python之在 Django 中用于测试的模拟图像

2024年10月24日42bluestorm

我想使用模拟图像在 Django 中创建一个对象。

测试.py:

from django.test import TestCase 
from .models import MyModel 
from unittest import mock 
from django.core.files import File 
 
 
class MyModelTestCase(TestCase): 
 
    def setUp(self): 
        file_mock = mock.Mock(spec=File, name='FileMock') 
        file_mock.name = 'test.png' 
        MyModel.objects.create(img=file_mock, name='123',) 
 
    def test_creation(self): 
        obj =  MyModel.objects.get(name='123') 
        self.assertEqual(obj, '1, 123') 

但是我有一个错误:

TypeError: 'Mock' does not support the buffer interface 

我使用spec-argument,它是如何在documentation中描述的.

为什么它不起作用以及如何解决?

谢谢!

更新

如果我在 setUp() 中使用它:

file_mock.read.return_value = b'my_img_data' 

然后运行测试,没有任何反应:

Creating test database for alias 'default'... 

因此,没有错误,也没有运行测试。

更新 1:

在 setUP() 中:

image = Image.new('RGBA', size=(50,50), color=(256,0,0)) 
image_file = BytesIO(image.tostring()) 
file = InMemoryUploadedFile(image_file, None, 'test.jpg', 'image/jpg', 1024, None) 
MyModel.objects.create(img=file, name='123',)  

它会产生新的错误:

TypeError: 'NoneType' object is not subscriptable 

回溯:

Creating test database for alias 'default'... 
E 
====================================================================== 
ERROR: test_creation () 
---------------------------------------------------------------------- 
Traceback (most recent call last): 
  File "dir/graffities/tests.py", line 21, in setUp 
    MyModel.objects.create(img=file, name='123',) 
  File "dir/env/lib/python3.4/site-packages/django/db/models/manager.py", line 127, in manager_method 
    return getattr(self.get_queryset(), name)(*args, **kwargs) 
  File "dir/env/lib/python3.4/site-packages/django/db/models/query.py", line 346, in create 
    obj = self.model(**kwargs) 
  File "dir/env/lib/python3.4/site-packages/django/db/models/base.py", line 482, in __init__ 
    signals.post_init.send(sender=self.__class__, instance=self) 
  File "dir/env/lib/python3.4/site-packages/django/dispatch/dispatcher.py", line 201, in send 
    response = receiver(signal=self, sender=sender, **named) 
  File "dir/env/lib/python3.4/site-packages/django/db/models/fields/files.py", line 477, in update_dimension_fields 
    width = file.width 
  File "dir/env/lib/python3.4/site-packages/django/core/files/images.py", line 17, in _get_width 
    return self._get_image_dimensions()[0] 
TypeError: 'NoneType' object is not subscriptable 
 
---------------------------------------------------------------------- 
Ran 1 test in 0.071s 
 
FAILED (errors=1) 

更新 2:

模型.py:

class MyModel(models.Model): 
    width = models.PositiveIntegerField(editable=False,) 
    height = models.PositiveIntegerField(editable=False,) 
    img = models.ImageField(upload_to = get_file_path, height_field='height', width_field='width') 
    name = models.CharField('Название', max_length=50) 

请您参考如下方法:

您是否尝试过使用 MagicMock?不过,我怀疑它会有所帮助。问题是,MyModel.objects.create 要求您的模拟对象在您的 file_mock 上调用 .read() 等方法时返回有用的值实例。但是,mocks 首先只返回 mocks,您必须配置 mock 的返回值和属性,以便 MyModel.objects.create 可以使用它。 根据您对数据库中的图像文件执行的操作,我假设一个简单的 StringIO 实例和任意数据可能足以为图像文件提供 stub 。

更新

您的 MyModel.objects.create(img=file, name='123',) 需要 django.core.files.ImageFile实例。所以你需要将 BytesIO 缓冲区传递给 ImageFile 并且你可能必须将图像保存到缓冲区中,我不确定是否Image.tostring 可以工作:

image = Image.new('RGBA', size=(50,50), color=(256,0,0)) 
image_file = BytesIO() 
image.save(image_file, 'PNG') # or whatever format you prefer 
file = ImageFile(image_file) 
MyModel.objects.create(img=file, name='123',)