2

I have a method that does the following:

    import os

    ...

    if not os.path.exists(dirpath):
        os.makedirs(dirpath)

I'm trying to mock the makedirs and path.exists but when I do this with patch the mocks conflict:

@patch('os.makedirs')
@patch('os.path.exists')
def test_foo(self, makedirs, exists):
    c = Config()
    c.foo()

    assert makedirs.called
    assert exists.called

If I disable either makedirs or exists they both work fine but have an issue when being used together.

I've also tried using with patch('os.makedirs') as makedirs: syntax which doesn't change anything.

Does anyone know why they are conflicting or what I can do to resolve this?

Thanks!

MysteriousWaffle
  • 439
  • 1
  • 5
  • 16

1 Answers1

2

If you mock os.path.exists as you do, it will return a mock, which always evaluates to True - so your code will never reach os.makedirs. To make this work, you have to provide a return value for the mock:

@patch('os.makedirs')
@patch('os.path.exists', return_value=False)
def test_foo(self, exists, makedirs):
    c = Config()
    c.foo()

    makedirs.assert_called_once()
    exists.assert_called_once()

Note also that the order of the mocks was reverted in your code - the argument for the last patch decorator has to go first.

I have also replaced assert xx.called with xx.assert_called_once() - the assert_called_... methods of Mock provide more fine-grained possibilities for checks.

MrBean Bremen
  • 14,916
  • 3
  • 26
  • 46