unit-testingpytestpytest-mock

In pytest returns magicMock instance instead of return value


i have a sample method and a pytest method for it.

import pytest
from datetime import datetime


# this is the method to test
def get_time_of_day():
    """return string Night/Morning/Afternoon/Evening depending on the hours range"""
    time = datetime.now()
    print(time.hour)
    if 0 <= time.hour <6:
        return "Night"
    if 6 <= time.hour < 12:
        return "Morning"
    if 12 <= time.hour <18:
        return "Afternoon"
    return "Evening"

#pytest method, where I am trying to mock datetime.now
def test_get_time_of_day(mocker):
    mock_now = mocker.patch("tests.test_sample.datetime")
    mock_now.now.return_value = datetime(2016, 5, 20, 14, 10, 0)

    assert get_time_of_day() == "Afternoon"

But when I try to run the pytest as follow

python3 -m pytest test_sample.py

I get TypeError: '<=' not supported between instances of 'int' and 'MagicMock'

I have a directory tests inside that I have the python file test_sample.py. In this file, I have written this code.

I have referred this page:

So do anyone Know to solve this issue. Thank you


Solution

  • This is because when you are assigning a value to mock_now.now.return_value, datetime is already patched and returns a MagicMock instead of the datetime object as you expect.

    This would work:

    def test_get_time_of_day(mocker):
        dt = datetime(2016, 5, 20, 14, 10, 0)
        mock_now = mocker.patch("tests.test_sample.datetime")
        mock_now.now.return_value = dt
    
        assert get_time_of_day() == "Afternoon"
    

    As you would typically patch objects in modules that you test (instead of within the test module itself), you would not run into this issue.