0

I have one class with a method that instantiates an element of a second class:

class FirstClass:

    def method_one():
        second_class = SecondClass()

the second class has a method with a default argument:

class SecondClass:
    def method_two(important_date: datetime.date = get_today())

and a function get_today in a different file date_service:

def get_today() -> datetime.date:
    return datetime.date.today()

I am testing method_one in a test_first_class.py and I don't manage to mock the value of get_today().

I looked at several pages and solutions in SO and I couldn't fix it. Some of the ideas:

  • I tried that but in the line
with patch.object(build_url, 'func_defaults', ('domain',)):

I don't know what I have to put at build_url. I tried something like SecondClass.method_two and it doesn't work.

REMARK: I know that a good unit test should test FirstClass and SecondClass independently, and mock method_two in test_first_class.py but for some reasons I can't do that :-(

xavier
  • 1,860
  • 4
  • 18
  • 46
  • 1
    Your program might give undesirable results if it runs through midnight. – Klaus D. Feb 19 '21 at 15:21
  • In my case it's not a big deal, but I understand what you mean. Which would be a solution? If it runs through midnight, there is not way to avoid potential undesirable results, is there? – xavier Feb 19 '21 at 15:24
  • Have you tried understanding the doc ? https://docs.python.org/3/library/unittest.mock.html#patch-object (not an expert in unitesting) – ygorg Feb 19 '21 at 15:27
  • 2
    Instead of getting the day one as am argument default, use `None` as the default and handle it in the method to always get the recent day. – Klaus D. Feb 19 '21 at 16:21
  • Oh @Klaus D., you are right! I hadn't considered the fact that default arguments are loaded only once! Ok, I'll change it and I won't need then to mock it that way. Still, I found a solution and I'll post it in case anyone is interested. Thank you very much for your remark!!! – xavier Feb 22 '21 at 09:40

1 Answers1

1

I finally solved the problem doing the following:

@staticmethod
@patch('date_service.get_today', Mock(return_value=mock_today))
def test_something():
    importlib.reload(second_class)
    importlib.reload(first_class)
    first_class_element = FirstClass()
    whatever = first_class_element.method_one()
    assert (...)

where second_class and first_class contain SecondClass and FirstClass, respectively; and mock_today is the date I use to mock today.

Attention: you need to reload BOTH classes, and in this very order, otherwise, it doesn't work.

Remark: as per @Klaus D. comment, I finally couldn't use get_today() as a default optional argument and I didn't have to use all this mess, but I give the answer in case anyone needs it...

xavier
  • 1,860
  • 4
  • 18
  • 46