Python: 嘲笑 datetime.date.today()
Python: Mocking datetime.date.today()
试图让 mocking 为 datetime.date.today() 工作,在阅读这篇 answer and this documentation 之后,我终于让它工作了。虽然我的原始版本无法正常工作,但我想知道是否有人可以帮助我理解?
我最初的实现是在像这样 import datetime as dt
导入日期时间后调用 dt.date.today()
。这可以在 mymodule.today_string_dt_date
中看到。测试是通过模拟 mymodule.dt.date
(无法直接模拟 mymodule.dt.date.today
,因为它是内置的),并在导入 datetime
后设置 mock.today.return_value = dt.date(2016,1,10)
以与 mymodule.py
(import datetime as dt
)
然后我实现了一个直接导入 date
的版本 (from datetime import date
) 并创建了将 mock.today.return_value
设置为 dt.date(2016,1,10)
和 [=28= 的测试] 两个版本。从 运行 py.test -v
的输出中可以看出,除了我的原始版本之外的所有测试版本都通过了
看起来对模块和测试使用相同的导入方案 (import datetime as dt
) 并使用它来创建模拟 return 值(如在测试 test_today_string_dt_date
中)废墟模拟。
mymodule.py
import datetime as dt
from datetime import date
def today_string_dt_date():
return dt.date.today().strftime('%Y-%m-%d')
def today_string_date():
return date.today().strftime('%Y-%m-%d')
if __name__ == '__main__':
print(today_string_dt_date())
test_mymodule.py
import datetime as dt
from datetime import date
from unittest.mock import patch
import unittest
import mymodule
class MyTest(unittest.TestCase):
@patch('mymodule.dt.date')
def test_today_string_dt_date(self, mock_date):
mock_date.today.return_value = dt.date(2016, 1, 10)
assert mymodule.today_string_dt_date() == '2016-01-10'
@patch('mymodule.dt.date')
def test_today_string_dt_date_alt(self, mock_date):
mock_date.today.return_value = date(2016, 1, 10)
assert mymodule.today_string_dt_date() == '2016-01-10'
@patch('mymodule.date')
def test_today_string_date(self, mock_date):
mock_date.today.return_value = dt.date(2016, 1, 10)
assert mymodule.today_string_date() == '2016-01-10'
@patch('mymodule.date')
def test_today_string_date_alt(self, mock_date):
mock_date.today.return_value = date(2016, 1, 10)
assert mymodule.today_string_date() == '2016-01-10'
py.test输出
=========================== test session starts ===========================
platform darwin -- Python 3.5.1, pytest-2.8.5, py-1.4.31, pluggy-0.3.1
collected 4 items
test_mymodule.py::MyTest::test_today_string_date PASSED
test_mymodule.py::MyTest::test_today_string_date_alt PASSED
test_mymodule.py::MyTest::test_today_string_dt_date FAILED
test_mymodule.py::MyTest::test_today_string_dt_date_alt PASSED
================================ FAILURES =================================
____________________ MyTest.test_today_string_dt_date _____________________
self = <test_mymodule.MyTest testMethod=test_today_string_dt_date>
mock_date = <MagicMock name='date' id='4364815888'>
@patch('mymodule.dt.date')
def test_today_string_dt_date(self, mock_date):
mock_date.today.return_value = dt.date(2016, 1, 10)
> assert mymodule.today_string_dt_date() == '2016-01-10'
E AssertionError: assert <MagicMock name='date().strftime()' id='4353329528'> == '2016-01-10'
E + where <MagicMock name='date().strftime()' id='4353329528'> = <function today_string_dt_date at 0x10429ed90>()
E + where <function today_string_dt_date at 0x10429ed90> = mymodule.today_string_dt_date
test_mymodule.py:14: AssertionError
=================== 1 failed, 3 passed in 0.05 seconds ====================
这只是因为 @patch('mymodule.dt.date')
您正在修补 datetime
模块中的原始 date
引用。在此上下文中,dt.date(2016, 1, 10)
是 MagicMock
,其中名称为 date()
。
据此你有 today_string_dt_date()
将 return 一个 date().strftime()
MagicMock
.
我承认这有点扭曲,正是为了这类事情,我尽量避免在补丁中使用复杂的路径:我的规则是
- 尝试只修补根引用。
- 如果您无法关注 1(带有
from a import b
的模块),只需修补模块参考,永远不要浏览它。
试图让 mocking 为 datetime.date.today() 工作,在阅读这篇 answer and this documentation 之后,我终于让它工作了。虽然我的原始版本无法正常工作,但我想知道是否有人可以帮助我理解?
我最初的实现是在像这样 import datetime as dt
导入日期时间后调用 dt.date.today()
。这可以在 mymodule.today_string_dt_date
中看到。测试是通过模拟 mymodule.dt.date
(无法直接模拟 mymodule.dt.date.today
,因为它是内置的),并在导入 datetime
后设置 mock.today.return_value = dt.date(2016,1,10)
以与 mymodule.py
(import datetime as dt
)
然后我实现了一个直接导入 date
的版本 (from datetime import date
) 并创建了将 mock.today.return_value
设置为 dt.date(2016,1,10)
和 [=28= 的测试] 两个版本。从 运行 py.test -v
看起来对模块和测试使用相同的导入方案 (import datetime as dt
) 并使用它来创建模拟 return 值(如在测试 test_today_string_dt_date
中)废墟模拟。
mymodule.py
import datetime as dt
from datetime import date
def today_string_dt_date():
return dt.date.today().strftime('%Y-%m-%d')
def today_string_date():
return date.today().strftime('%Y-%m-%d')
if __name__ == '__main__':
print(today_string_dt_date())
test_mymodule.py
import datetime as dt
from datetime import date
from unittest.mock import patch
import unittest
import mymodule
class MyTest(unittest.TestCase):
@patch('mymodule.dt.date')
def test_today_string_dt_date(self, mock_date):
mock_date.today.return_value = dt.date(2016, 1, 10)
assert mymodule.today_string_dt_date() == '2016-01-10'
@patch('mymodule.dt.date')
def test_today_string_dt_date_alt(self, mock_date):
mock_date.today.return_value = date(2016, 1, 10)
assert mymodule.today_string_dt_date() == '2016-01-10'
@patch('mymodule.date')
def test_today_string_date(self, mock_date):
mock_date.today.return_value = dt.date(2016, 1, 10)
assert mymodule.today_string_date() == '2016-01-10'
@patch('mymodule.date')
def test_today_string_date_alt(self, mock_date):
mock_date.today.return_value = date(2016, 1, 10)
assert mymodule.today_string_date() == '2016-01-10'
py.test输出
=========================== test session starts ===========================
platform darwin -- Python 3.5.1, pytest-2.8.5, py-1.4.31, pluggy-0.3.1
collected 4 items
test_mymodule.py::MyTest::test_today_string_date PASSED
test_mymodule.py::MyTest::test_today_string_date_alt PASSED
test_mymodule.py::MyTest::test_today_string_dt_date FAILED
test_mymodule.py::MyTest::test_today_string_dt_date_alt PASSED
================================ FAILURES =================================
____________________ MyTest.test_today_string_dt_date _____________________
self = <test_mymodule.MyTest testMethod=test_today_string_dt_date>
mock_date = <MagicMock name='date' id='4364815888'>
@patch('mymodule.dt.date')
def test_today_string_dt_date(self, mock_date):
mock_date.today.return_value = dt.date(2016, 1, 10)
> assert mymodule.today_string_dt_date() == '2016-01-10'
E AssertionError: assert <MagicMock name='date().strftime()' id='4353329528'> == '2016-01-10'
E + where <MagicMock name='date().strftime()' id='4353329528'> = <function today_string_dt_date at 0x10429ed90>()
E + where <function today_string_dt_date at 0x10429ed90> = mymodule.today_string_dt_date
test_mymodule.py:14: AssertionError
=================== 1 failed, 3 passed in 0.05 seconds ====================
这只是因为 @patch('mymodule.dt.date')
您正在修补 datetime
模块中的原始 date
引用。在此上下文中,dt.date(2016, 1, 10)
是 MagicMock
,其中名称为 date()
。
据此你有 today_string_dt_date()
将 return 一个 date().strftime()
MagicMock
.
我承认这有点扭曲,正是为了这类事情,我尽量避免在补丁中使用复杂的路径:我的规则是
- 尝试只修补根引用。
- 如果您无法关注 1(带有
from a import b
的模块),只需修补模块参考,永远不要浏览它。