2

test.py

@patch('I want to patch datetime.datetime.now here')
def test_function():
    import my_module
    my_module.some_function()
    ...

my_module.py

from datetime import datetime

def some_function():
    now = datetime.now()

By the way, I'm using pytest.

jonrsharpe
  • 115,751
  • 26
  • 228
  • 437
laike9m
  • 18,344
  • 20
  • 107
  • 140

2 Answers2

3

I think freezegun might be the module you're looking for.

baldr
  • 2,891
  • 11
  • 43
  • 61
-1

You need to patch the specific import you want to replace, and provide a parameter for the mock; try something like:

from unittest.mock import patch

import my_module

@patch('my_module.datetime')
def test_function(datetime):
    datetime.now.return_value = ...
    my_module.some_function()
    ...
    datetime.now.assert_called_once_with()

To only patch now, use:

@patch.object('my_module.datetime', 'now')
def test_function(now):
    now.return_value = ...
    my_module.some_function()
    ...
    now.assert_called_once_with()
jonrsharpe
  • 115,751
  • 26
  • 228
  • 437
  • 2
    There's a problem here. I don't want to patch the whole datetime class, just `datetime.now()`, cause I need other methods. – laike9m Jan 10 '16 at 15:23
  • It says: `AttributeError: type object 'datetime.datetime' has no attribute 'rsplit'` – laike9m Jan 10 '16 at 15:26
  • @laike9m which line, the patch? Maybe I missed some quotes – jonrsharpe Jan 10 '16 at 15:28
  • @laike9m did that work? I'm out of the house so can't test, sorry. – jonrsharpe Jan 10 '16 at 15:45
  • @laike9m double-checking in [my own project](https://github.com/textbook/halliwell/blob/657c00b200a68cd0dbdd3e93e272ae739cd82e07/tests/parser/test_person.py#L63), the first argument should be an object, not a string. – jonrsharpe Jan 10 '16 at 15:51
  • No. I patched two other things, now it says `fixture 'mock_upvote_time' not found`, `mock_upvote_time` is another patched function which works before adding `@patch('utils.datetime', 'now')` – laike9m Jan 10 '16 at 15:51
  • @laike9m you will need to put any fixtures *before* the injected mock. Patches appear in the parameter list *"inside out"*, also worth noting (see e.g. http://stackoverflow.com/questions/27342149/decorator-execution-order). A [mcve] of your actual situation would have made this much easier; could you edit the question accordingly? – jonrsharpe Jan 10 '16 at 15:53
  • I'm sure the other two patches are correct. Tried all kinds of combinations still can't get it working. – laike9m Jan 10 '16 at 15:57
  • @laike9m it is a waste of both of our time for me to debug what I *guess* you're doing. Please edit the question to give a useful example, with the specific error(s) you're seeing, or you might as well just delete it. – jonrsharpe Jan 10 '16 at 16:03
  • @laike9m see [here](https://github.com/textbook/halliwell/blob/493c7371724ff4457cb3a416cb0d732f0a8e8fc6/tests/test_bot.py#L53) for an example with both patch and fixture; patches should be *first*, sorry. – jonrsharpe Jan 10 '16 at 16:06
  • 2
    OK I found a similar question:http://stackoverflow.com/questions/4481954/python-trying-to-mock-datetime-date-today-but-not-working, though it doesn't seem to apply to me cause I can't replace things in another module. Anyway, `mock` is unable to do patch this, according to that question and my experiments. – laike9m Jan 10 '16 at 16:11