TypeError:__str__返回了非字符串(类型MagicMock)

时间:2019-08-17 14:48:14

标签: python django python-3.x mocking

我正在为Django代码编写一些测试,并且正在模拟文件和文件存储。

我已经找到了本指南

https://joeray.me/mocking-files-and-file-storage-for-testing-django-models.html

所以我的模拟看起来像这样

# mocks.py
image_mock = mock.MagicMock(spec=File, name='FileMock')
image_mock.name = 'dummy.jpg'

storage_mock = mock.MagicMock(spec=Storage, name='StorageMock')
storage_mock.url = mock.MagicMock(name='url')
storage_mock.url.return_value = '/tmp/dummy.jpg'

任何失败的测试都是这样的:

import factory
import mock
from imagekit.signals import source_saved
from .mocks import storage_mock, image_mock
from .models import Car


@factory.django.mute_signals(source_saved)
class CarFactory(factory.django.DjangoModelFactory):
    class Meta:
        model = Car

    image = image_mock


def test_case_one(self):
    with mock.patch('django.core.files.storage.default_storage._wrapped', storage_mock):
        car = CarFactory.create()

它失败并显示以下错误:

_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
/home/admin/.virtualenvs/car-project/lib/python3.7/site-packages/factory/base.py:564: in create
    return cls._generate(enums.CREATE_STRATEGY, kwargs)
/home/admin/.virtualenvs/car-project/lib/python3.7/site-packages/factory/django.py:337: in wrapped_generate
    return generate_method(*args, **kwargs)
/home/admin/.virtualenvs/car-project/lib/python3.7/site-packages/factory/django.py:141: in _generate
    return super(DjangoModelFactory, cls)._generate(strategy, params)
/home/admin/.virtualenvs/car-project/lib/python3.7/site-packages/factory/base.py:501: in _generate
    return step.build()
/home/admin/.virtualenvs/car-project/lib/python3.7/site-packages/factory/builder.py:279: in build
    kwargs=kwargs,
/home/admin/.virtualenvs/car-project/lib/python3.7/site-packages/factory/base.py:315: in instantiate
    return self.factory._create(model, *args, **kwargs)
/home/admin/.virtualenvs/car-project/lib/python3.7/site-packages/factory/django.py:185: in _create
    return manager.create(*args, **kwargs)
/home/admin/.virtualenvs/car-project/lib/python3.7/site-packages/django/db/models/manager.py:82: in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
/home/admin/.virtualenvs/car-project/lib/python3.7/site-packages/django/db/models/query.py:422: in create
    obj.save(force_insert=True, using=self.db)
/home/admin/.virtualenvs/car-project/lib/python3.7/site-packages/django/db/models/base.py:741: in save
    force_update=force_update, update_fields=update_fields)
/home/admin/.virtualenvs/car-project/lib/python3.7/site-packages/django/db/models/base.py:779: in save_base
    force_update, using, update_fields,
/home/admin/.virtualenvs/car-project/lib/python3.7/site-packages/django/db/models/base.py:870: in _save_table
    result = self._do_insert(cls._base_manager, using, fields, update_pk, raw)
/home/admin/.virtualenvs/car-project/lib/python3.7/site-packages/django/db/models/base.py:908: in _do_insert
    using=using, raw=raw)
/home/admin/.virtualenvs/car-project/lib/python3.7/site-packages/django/db/models/manager.py:82: in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
/home/admin/.virtualenvs/car-project/lib/python3.7/site-packages/django/db/models/query.py:1186: in _insert
    return query.get_compiler(using=using).execute_sql(return_id)
/home/admin/.virtualenvs/car-project/lib/python3.7/site-packages/django/db/models/sql/compiler.py:1334: in execute_sql
    for sql, params in self.as_sql():
/home/admin/.virtualenvs/car-project/lib/python3.7/site-packages/django/db/models/sql/compiler.py:1278: in as_sql
    for obj in self.query.objs
/home/admin/.virtualenvs/car-project/lib/python3.7/site-packages/django/db/models/sql/compiler.py:1278: in <listcomp>
    for obj in self.query.objs
/home/admin/.virtualenvs/car-project/lib/python3.7/site-packages/django/db/models/sql/compiler.py:1277: in <listcomp>
    [self.prepare_value(field, self.pre_save_val(field, obj)) for field in fields]
/home/admin/.virtualenvs/car-project/lib/python3.7/site-packages/django/db/models/sql/compiler.py:1218: in prepare_value
    value = field.get_db_prep_save(value, connection=self.connection)
/home/admin/.virtualenvs/car-project/lib/python3.7/site-packages/django/db/models/fields/__init__.py:789: in get_db_prep_save
    return self.get_db_prep_value(value, connection=connection, prepared=False)
/home/admin/.virtualenvs/car-project/lib/python3.7/site-packages/django/db/models/fields/__init__.py:784: in get_db_prep_value
    value = self.get_prep_value(value)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <django.db.models.fields.files.ImageField: image>
value = <[TypeError("__str__ returned non-string (type MagicMock)") raised in repr()] ImageFieldFile object at 0x7f2c94996a58>

    def get_prep_value(self, value):
        value = super().get_prep_value(value)
        # Need to convert File objects provided via a form to string for database insertion
        if value is None:
            return None
>       return str(value)
E       TypeError: __str__ returned non-string (type MagicMock)

对此我将不胜感激。


要求:

python 3.7

Django == 2.2

django-storages == 1.7.1

factory-boy == 2.12.0

mock == 3.0.5

1 个答案:

答案 0 :(得分:0)

您还必须像这样修补ImageField

image_name = 'test_image.jpg'
image_field_mock = mock.MagicMock(name='get_db_prep_save')
image_field_mock.return_value = image_name


def test_case_one(self):
    with mock.patch('django.core.files.storage.default_storage._wrapped', storage_mock):
        with mock.patch('django.db.models.ImageField.get_db_prep_save', image_field_mock):
            car = CarFactory.create()