0

I'm trying to unit test a class, let's call it A. As part of A's instantiation, it tries to create instances of many classes from a package external.

from external import B, C, D

class A
    def __init__(self, some_config):
        b_config, c_config, d_config = self._generate_config(some_config)
        b = B(b_config)
        c = C(c_config)
        d = D(d_config)

I don't want to instantiate anything from external for my unit test, but the nature of the codebase is that I also don't want to pass b, c, or d in as external arguments for the constructor.

I know using mock.patch, I can write a test

@mock.patch(external.D, autospec=True)
@mock.patch(external.C, autospec=True)
@mock.patch(external.B, autospec=True)
def test(self, b_patch: mock.MagicMock,
               c_patch: mock.MagicMock,
               d_patch: mock.MagicMock):
    b_patch.return_value = mock.Mock()
    c_patch.return_value = mock.Mock()
    d_patch.return_value = mock.Mock()

    test_a = A()
    # Assert no problems with instantiating A
    # AKA self._generate_config worked

But is there an easy way to mark all classes inside external such that they should be mocked like above?

1 Answer 1

1

Your sample code isn't self-consistent -- in your first example you're doing from external import B and in the second example it looks like you did import external. In the second form you're able to just patch external:

import external

class A:
    def __init__(self):
        b = external.B()
        c = external.C()
        d = external.D()

from unittest.mock import patch

@patch('__main__.external')
def test(mock_external):
    test_a = A()

test()

The above test passes regardless of the contents of external.py (as long as it doesn't raise an error on the initial import) because the test patches out the entire module.

It's not necessary to individually assign all the different attributes of external to Mock objects because every attribute of a Mock is already an auto-created Mock unless you set it to something else.

If there is no external name in the module under test (because you did from external import B etc) you need to individually patch the B, C, and D names.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.