我想使用模拟图像在 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',)
