如何在单元测试中优雅地交换(修补)Django FileSystemStorage 设置?
我面临以下问题。我有一个看起来有点像这样的模型:
class Package(models.Model):
name = models.CharField(max_length=64)
file = models.FileField(upload_to="subdir",
storage=settings.PACKAGE_STORAGE,
null=True)
此示例中的基本内容是 FileField
构造函数的 storage=
参数。它填充了来自 settings.py
的值。其中有以下代码:
from django.core.files.storage import FileSystemStorage
PACKAGE_STORAGE = FileSystemStorage(location="/var/data", base_url="/")
对于生产使用,效果很好。但在我的单元测试中,我上传的内容现在写入 /var/data
,其中包含生产数据。我尝试像这样交换packages/tests.py
中的PACKAGE_STORE
,
from django.conf import settings # This is line 1
from tempfile import mkdtemp
settings.PACKAGE_STORAGE = FileSystemStorage(location=mkdtemp(), base_url="/")
# rest of the imports and testing code below
但真正的问题是在加载测试文件之前, packages
应用程序及其模型已加载,因此,在我能够在测试设置代码中更改它之前,PACKAGE_STORAGE
设置已得到解决。
是否有一种优雅的方法可以在测试上下文中覆盖此特定设置?
I'm faced with the following problem. I have a Model that looks somewhat like this:
class Package(models.Model):
name = models.CharField(max_length=64)
file = models.FileField(upload_to="subdir",
storage=settings.PACKAGE_STORAGE,
null=True)
Essential in this example is the storage=
argument to the FileField
constructor. It is filled with a value from settings.py
. In there is the following code:
from django.core.files.storage import FileSystemStorage
PACKAGE_STORAGE = FileSystemStorage(location="/var/data", base_url="/")
For production use, this works fine. But in my unit tests, uploads I make are now written to /var/data
, which contains production data. I tried to swap out the PACKAGE_STORE
in packages/tests.py
like this
from django.conf import settings # This is line 1
from tempfile import mkdtemp
settings.PACKAGE_STORAGE = FileSystemStorage(location=mkdtemp(), base_url="/")
# rest of the imports and testing code below
but the real problem is that before the test file is loaded, the packages
app and its models have been loaded already, and therefore, the PACKAGE_STORAGE
setting has been resolved before I'm able to change it in the test setup code.
Is there an elegant way to override this specific setting in a testing context?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
不知道这是否算优雅,但您可以使用不同的设置文件进行测试...
类似:
然后使用测试设置运行测试,
python manage.py test --settings=test_settings.
Don't know if this counts as elegant, but you could use a different settings file for testing...
Something like:
Then run your test using the test settings,
python manage.py test --settings=test_settings
.动态覆盖模型上
FileField
实例的底层存储实现:Override the underlying storage implementation for instances of
FileField
on your model dynamically:如果你通过 django 运行测试,这
当然应该可以工作;)
if you run the test through django this should work
of course after ;)
我刚刚通过添加到我的自定义测试运行程序来解决这个问题。要了解如何添加自定义测试运行程序,请参阅 在 Django 文档中定义测试运行器。我的代码看起来像这样:
这会覆盖一些自定义测试套件方法。
setup_test_environment
备份以前的设置并将其存储在类属性中。teardown_test_environment
将它们设置回之前的状态。 run_tests 方法使用 try/finally 块来确保测试后删除临时目录,即使发生异常也是如此。I just solved this by adding to my custom test runner. To see how to add a custom test runner, see Defining a test runner in the Django documentation. My code looks something like this:
This overrides some of the custom test suite methods.
setup_test_environment
backs up the previous settings and stores them in a class attribute. Theteardown_test_environment
sets them back to what they were before. Therun_tests
method uses a try/finally block to make sure that the temporary directory is deleted after the tests, even if an exception happens.如果您使用 pytest-django 并希望保留单个 Django 配置文件,您可以创建一个conftest.py 并为每个执行的测试覆盖该设置(源)
您还可以在 Django 设置之前更改您的应用程序使用
pytest-django
。请参阅此处。If you are using
pytest-django
and want to keep a single Django configuration file you can create aconftest.py
and have that setting overridden for every test executed (source)You can also change your app before Django sets up using
pytest-django
. See here.回复晚了,但我花了很长时间才找到这个漂亮的小图书馆;
https://pypi.org/project/django-override-storage/
Late answer but it took me a long time to find this nice little library;
https://pypi.org/project/django-override-storage/
对于产品,我们使用 s3 和 boto3,但对于单元测试,使用很棒的 lib dj-inmemorystorage 只是将文件加载到内存中。
因此,我只是覆盖测试设置中的默认文件存储:
然后在测试中:
For prod we use a s3 and boto3 but for unit tests it is enough to use great lib dj-inmemorystorage which just loads the file to memory.
So, I just override the default file storage in my test settings:
then in the test: