关于python:django test mock datetime now

Django Test Mock Datetime Now

我有一个django测试,需要模拟datetime.now(),因为它测试的视图使用datetime.now()。

我正在使用迈克尔·福德的模拟库,版本1.0.1。我正在寻找一个不使用其他库(如Freezegun)的解决方案。

大多数例子都是这样的,这个导入日期时间并重写它,但是我正在导入datetime.datetime,我正在尝试重写它,因为某些原因,这个方法不起作用。

覆盖日期时间工作:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import mock
import datetime

class FixedDate(datetime.datetime):

    @classmethod
    def now(cls):
        return cls(2010, 1, 1)

@mock.patch('datetime.datetime', FixedDate)
def myTest():
    print(datetime.datetime.now())

myTest()

但我想导入datetime.datetime并执行如下操作:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import mock
from datetime import datetime

class FixedDate(datetime):

    @classmethod
    def now(cls):
        return cls(2010, 1, 1)

@mock.patch('datetime', FixedDate)
def myTest():
    print(datetime.now())

myTest()

这会导致类型错误:需要有效的目标来修补。您提供了:"datetime"。

模拟图书馆还指出:

target should be a string in the form ‘package.module.ClassName’. The target is imported and the specified object replaced with the new object, so the target must be importable from the environment you are calling patch from.

是否有任何方法只访问datetime而不访问datetime.datetime?

铌。我也看到了这个例子,但它对我来说不起作用,因为我没有一个返回日期时间的函数,但是我的视图使用了日期时间。


您应该在正在测试的模块中,而不是在带有测试的模块中,使用cx1〔0〕对象。

基于代码的最小工作示例:

App.Py

1
2
3
4
5
from datetime import datetime

def my_great_func():
    # do something
    return datetime.now()

tests.py(注意app.py中的datetime是如何修补的)

1
2
3
4
5
6
7
8
from datetime import datetime
from unittest import mock
from app import my_great_func

@mock.patch('app.datetime')
def test_my_great_func(mocked_datetime):
    mocked_datetime.now.return_value = datetime(2010, 1, 1)
    assert my_great_func() == datetime(2010, 1, 1)

测试执行结果:

1
2
3
4
5
6
7
8
9
10
11
$ pytest -vvv tests.py
======================= test session starts =========================
platform linux -- Python 3.5.2, pytest-3.2.1, py-1.4.34, pluggy-0.4.0
cachedir: .cache
rootdir: /home/kris/projects/tmp, inifile:
plugins: mock-1.6.2, celery-4.1.0
collected 1 item                                                  

tests.py::test_my_great_func PASSED

==================== 1 passed in 0.00 seconds =======================