Mocking a class Mock or patch?
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
In Python tests, Mock and patch solve related but different problems. Mock creates a fake object. patch temporarily replaces a real object at the lookup location your code under test uses, which often means the right answer is not "Mock or patch" but "patch with a Mock."
What Mock Does
Mock is a programmable stand-in. You can set return values, record calls, and simulate errors.
This is useful when you can inject the dependency directly into the function or class you are testing.
What patch Does
patch replaces an attribute for the duration of a test. The crucial rule is that you patch where the object is looked up, not where it was originally defined.
Here patch replaces service.ApiClient with a mock class. The object you interact with inside the test is still a mock, but patch is what inserts it into the code path.
Why The Lookup Location Matters
Suppose service.py contains this code:
If you patch api.ApiClient, the test may still call the original class because service.py already imported it into its own namespace. In that case you must patch service.ApiClient.
This is the single most common mocking mistake in Python.
When To Use Which
Use a plain Mock when you control dependency injection directly. For example, if a function accepts a client argument, you can pass a mock without patching anything.
Use patch when the code under test constructs or imports the dependency internally and you need to replace that object during the test.
In practice, many tests combine them: patch installs the replacement and the replacement is a Mock or MagicMock.
A Small Example With Dependency Injection
No patch is needed because the dependency arrives as an argument.
Another useful refinement is autospec or spec_set when you want mocks to behave more like the real object. That helps tests fail when code calls a method that does not actually exist on the dependency, which is often more valuable than a completely free-form mock that silently accepts everything. Stronger mock specifications make tests a little stricter and often more trustworthy.
Python also offers patch.object when you want to replace an attribute on a specific object rather than on a module path string. That can be convenient in narrower tests, but the same rule still applies: patch the attribute your code will actually read during the test, and keep the replacement scoped tightly so the test remains easy to reason about.
Common Pitfalls
One common mistake is patching the original definition instead of the lookup location used by the module under test. Patch the name your code actually resolves at runtime.
Another mistake is reaching for patch when a simple injected Mock would make the design cleaner and the test easier to read.
A third issue is forgetting that patched classes return mock instances through MockClass.return_value. If you are testing instance method calls, that is the object you usually need to configure.
Summary
- '
Mockcreates a fake object.' - '
patchtemporarily replaces a real object in the lookup path used by the code under test.' - Many tests use both together:
patchinstalls the fake andMockprovides the behavior. - If patching fails mysteriously, check whether you patched the wrong module path.

