I have a class Foo that creates instances of other classes A, B, and C in its constructor. A, B, and C share the same constructor parameter and are used in other parts of the codebase, not just in Foo. A, B, and C access an outside resource configured by the passed parameter. In unit tests, A, B, and C are mocked out with unittest.mock.patch.

class Foo(object):
    def __init__(self, param):
        self.a = A(param)
        self.b = B(param)
        self.c = C(param)

foo = Foo('param')

Would the following be an improvement or just unnecessary code? Is passing in unittest.mock.Mock objects in tests preferred over using unittest.mock.patch? In practice, A, B, and C should always share the same parameter.

class Foo(object):
    def __init__(self, a, b, c):
        self.a = a
        self.b = b
        self.c = c

    def from_param(cls, param):
        return cls(A(param), B(param), C(param))

foo = Foo.from_param('param')
  • 1
    Is the “should always share the same parameter” an invariant or just the current use-case? – 5gon12eder Jan 20 '16 at 19:03
  • Current use-case, but unlikely to change. A, B, and C are all wrappers around different groups of endpoints around a web service and share the same base URL. – user95275 Jan 20 '16 at 20:11

This is a little hard to reason about in isolation but I generally like the second approach better. It gives you the flexibility to pass any three objects (including your mocks). If it is not a class invariant that they all be constructed with the same parameters, this seems to be a good thing. The classmethod you provide for the case that you want A, B, C constructed with the same parameters makes it still convenient to use in the common case. And you can add more convenience factory functions later shall there be a need.

Of course, you shouldn't over-abstract either but the fact that you think about mocking hints me that this is not the case here.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.