简体   繁体   English

类型错误:__str__ 返回非字符串(类型 MagicMock)

[英]TypeError: __str__ returned non-string (type MagicMock)

I'm writing some tests for my Django code and I'm mocking file and file storage.我正在为我的 Django 代码编写一些测试,我是 mocking 文件和文件存储。

I've found this guide我找到了这个指南

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

so my mocks look like this所以我的模拟看起来像这样

# 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'

any my failing test looks like this:我的任何失败测试都是这样的:

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()

And it fails with the following error:它失败并出现以下错误:

_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
/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)

I'd appreciate any help with this.我将不胜感激任何帮助。


Requirements:要求:

python 3.7 python 3.7

Django==2.2 Django==2.2

django-storages==1.7.1 django-storages==1.7.1

factory-boy==2.12.0工厂男孩==2.12.0

mock==3.0.5模拟==3.0.5

You must also patch ImageField like this您还必须像这样修补 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()

I tried the same guide and ran into the same issue and ultimately I was not able to get it to work.我尝试了相同的指南并遇到了相同的问题,最终我无法让它工作。 Instead I used: https://github.com/danifus/django-override-storage .相反,我使用了: https://github.com/danifus/django-override-storage That ended up being a much simpler to way to override the file storage when testing in Django.在 Django 中测试时,这最终成为一种更简单的覆盖文件存储的方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM