Python unittest patch using custom mock classHow do I test a private function or a class that has private methods, fields or inner classes?Calling an external command in PythonWhat are metaclasses in Python?Finding the index of an item given a list containing it in PythonWhat is the difference between Python's list methods append and extend?How can I safely create a nested directory?Does Python have a ternary conditional operator?How to get the current time in PythonHow can I make a time delay in Python?Does Python have a string 'contains' substring method?
Find the C-factor of a vote
How long would it take to cross the Channel in 1890's?
How do I handle a table mixing up the DM and the players' roles too often?
Why does the Saturn V have standalone inter-stage rings?
Is "Busen" just the area between the breasts?
Parameterize chained calls to a utility program in Bash
Non-flat partitions of a set
What reason would an alien civilization have for building a Dyson Sphere (or Swarm) if cheap Nuclear fusion is available?
Why aren't non-isolated DC-DC converters made for high wattage applications?
How do I professionally let my manager know I'll quit over smoking in the office?
What's currently blocking the construction of the wall between Mexico and the US?
What exactly is the 'online' in OLAP and OLTP?
Should developer taking test phones home or put in office?
Are all instances of trolls turning to stone ultimately references back to Tolkien?
Suggested order for Amazon Prime Doctor Who series
Why do some professors with PhDs leave their professorships to teach high school?
If I wouldn't want to read the story, is writing it still a good idea?
Can Ogre clerics use Purify Food and Drink on humanoid characters?
"How can you guarantee that you won't change/quit job after just couple of months?" How to respond?
If plants "alternate generations" between sporophytes and gametophytes, why don't we say the same of humans?
What happens when auto number reaches its pre-set max?
Silly doubt about tidal effects and Einstein Field Equations
Can you find x?
How to colour a table with opaque colour such that no text and no lines are visible?
Python unittest patch using custom mock class
How do I test a private function or a class that has private methods, fields or inner classes?Calling an external command in PythonWhat are metaclasses in Python?Finding the index of an item given a list containing it in PythonWhat is the difference between Python's list methods append and extend?How can I safely create a nested directory?Does Python have a ternary conditional operator?How to get the current time in PythonHow can I make a time delay in Python?Does Python have a string 'contains' substring method?
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty height:90px;width:728px;box-sizing:border-box;
I am testing a relatively simple piece of code that uses two relatively complex object that requires disk access. The complex objects are from a library. I would like to mock these library objects and assert that some of their member functions were called with particular values, depending on the input.
The calls that I use rely on some internal state of the library objects. I recognise that I can mock every function call on the complex objects individually, and set a return_value
before each. This seems much messier and painful than it needs to be, though.
It seems like you should be able to provide a custom class and wrap it with a Mock object to track all the calls to member functions. I've spent a few hours trying to make sense of the official documentation, and the closest I've found is the wraps
argument. Unfortunately, this doesn't seem to replace all the members with mocks that wrap, instead, it just uses the member variables of the mock object, only tracking the calls to __init__
.
e.g. in module_a.py:
# Assuming some library class that acts something like this:
class A:
def __init__(self, filename):
self.filename = filename
def get(self):
# ... Some complicated code, involving state and disk access ...
return something
def some_fnc(filename):
a = A(filename)
a.get()
a.get()
a.get()
a.get()
in test_module_a.py:
import unittest
import unittest.mock
import module_a
class MockA:
def __init__(self, *args, **kwargs):
self.i = 0
pass
def get(self):
# Fake version that returns dummy values,
# but more complicated than simply returning some value.
# Easy to reason about. If this gets complicated then you have problems.
print(self.i, 'is gotten')
if self.i > 3:
return 5
self.i += 1
return 1
class SomeFncTestCase(unittest.TestCase):
@unittest.mock.patch('module_a.A', wraps=MockA)
def test_it(self, m):
module_a.some_fnc('in_file')
m.assert_called_with('in_file')
m.get.assert_called()
MockA.get is called, and the first assert passes, but the second assert fails.
Is there some functionality that I'm missing? Is it possible to do what I want? Is there any reason why what I'm suggesting is particularly bad?
python unit-testing
add a comment |
I am testing a relatively simple piece of code that uses two relatively complex object that requires disk access. The complex objects are from a library. I would like to mock these library objects and assert that some of their member functions were called with particular values, depending on the input.
The calls that I use rely on some internal state of the library objects. I recognise that I can mock every function call on the complex objects individually, and set a return_value
before each. This seems much messier and painful than it needs to be, though.
It seems like you should be able to provide a custom class and wrap it with a Mock object to track all the calls to member functions. I've spent a few hours trying to make sense of the official documentation, and the closest I've found is the wraps
argument. Unfortunately, this doesn't seem to replace all the members with mocks that wrap, instead, it just uses the member variables of the mock object, only tracking the calls to __init__
.
e.g. in module_a.py:
# Assuming some library class that acts something like this:
class A:
def __init__(self, filename):
self.filename = filename
def get(self):
# ... Some complicated code, involving state and disk access ...
return something
def some_fnc(filename):
a = A(filename)
a.get()
a.get()
a.get()
a.get()
in test_module_a.py:
import unittest
import unittest.mock
import module_a
class MockA:
def __init__(self, *args, **kwargs):
self.i = 0
pass
def get(self):
# Fake version that returns dummy values,
# but more complicated than simply returning some value.
# Easy to reason about. If this gets complicated then you have problems.
print(self.i, 'is gotten')
if self.i > 3:
return 5
self.i += 1
return 1
class SomeFncTestCase(unittest.TestCase):
@unittest.mock.patch('module_a.A', wraps=MockA)
def test_it(self, m):
module_a.some_fnc('in_file')
m.assert_called_with('in_file')
m.get.assert_called()
MockA.get is called, and the first assert passes, but the second assert fails.
Is there some functionality that I'm missing? Is it possible to do what I want? Is there any reason why what I'm suggesting is particularly bad?
python unit-testing
It looks like you actually wantside_effect=[1, 1, 1, 5]
for the get method. Note that you're mocking the class, so the "real result" thatwraps
returns is the unwrapped instance, that's why only__init__
calls are tracked.
– jonrsharpe
Mar 25 at 8:39
This is just a toy example. I want the side effects to be programmatically determined. (i.e. the side_effects are based on the inputs, e.g. a function that is just a switch statement).
– Multihunter
Mar 26 at 2:52
1
A side effect can also be a function, as you only have one method. But your solution below also addresses it, wrapping an instance rather than the class.
– jonrsharpe
Mar 26 at 7:02
add a comment |
I am testing a relatively simple piece of code that uses two relatively complex object that requires disk access. The complex objects are from a library. I would like to mock these library objects and assert that some of their member functions were called with particular values, depending on the input.
The calls that I use rely on some internal state of the library objects. I recognise that I can mock every function call on the complex objects individually, and set a return_value
before each. This seems much messier and painful than it needs to be, though.
It seems like you should be able to provide a custom class and wrap it with a Mock object to track all the calls to member functions. I've spent a few hours trying to make sense of the official documentation, and the closest I've found is the wraps
argument. Unfortunately, this doesn't seem to replace all the members with mocks that wrap, instead, it just uses the member variables of the mock object, only tracking the calls to __init__
.
e.g. in module_a.py:
# Assuming some library class that acts something like this:
class A:
def __init__(self, filename):
self.filename = filename
def get(self):
# ... Some complicated code, involving state and disk access ...
return something
def some_fnc(filename):
a = A(filename)
a.get()
a.get()
a.get()
a.get()
in test_module_a.py:
import unittest
import unittest.mock
import module_a
class MockA:
def __init__(self, *args, **kwargs):
self.i = 0
pass
def get(self):
# Fake version that returns dummy values,
# but more complicated than simply returning some value.
# Easy to reason about. If this gets complicated then you have problems.
print(self.i, 'is gotten')
if self.i > 3:
return 5
self.i += 1
return 1
class SomeFncTestCase(unittest.TestCase):
@unittest.mock.patch('module_a.A', wraps=MockA)
def test_it(self, m):
module_a.some_fnc('in_file')
m.assert_called_with('in_file')
m.get.assert_called()
MockA.get is called, and the first assert passes, but the second assert fails.
Is there some functionality that I'm missing? Is it possible to do what I want? Is there any reason why what I'm suggesting is particularly bad?
python unit-testing
I am testing a relatively simple piece of code that uses two relatively complex object that requires disk access. The complex objects are from a library. I would like to mock these library objects and assert that some of their member functions were called with particular values, depending on the input.
The calls that I use rely on some internal state of the library objects. I recognise that I can mock every function call on the complex objects individually, and set a return_value
before each. This seems much messier and painful than it needs to be, though.
It seems like you should be able to provide a custom class and wrap it with a Mock object to track all the calls to member functions. I've spent a few hours trying to make sense of the official documentation, and the closest I've found is the wraps
argument. Unfortunately, this doesn't seem to replace all the members with mocks that wrap, instead, it just uses the member variables of the mock object, only tracking the calls to __init__
.
e.g. in module_a.py:
# Assuming some library class that acts something like this:
class A:
def __init__(self, filename):
self.filename = filename
def get(self):
# ... Some complicated code, involving state and disk access ...
return something
def some_fnc(filename):
a = A(filename)
a.get()
a.get()
a.get()
a.get()
in test_module_a.py:
import unittest
import unittest.mock
import module_a
class MockA:
def __init__(self, *args, **kwargs):
self.i = 0
pass
def get(self):
# Fake version that returns dummy values,
# but more complicated than simply returning some value.
# Easy to reason about. If this gets complicated then you have problems.
print(self.i, 'is gotten')
if self.i > 3:
return 5
self.i += 1
return 1
class SomeFncTestCase(unittest.TestCase):
@unittest.mock.patch('module_a.A', wraps=MockA)
def test_it(self, m):
module_a.some_fnc('in_file')
m.assert_called_with('in_file')
m.get.assert_called()
MockA.get is called, and the first assert passes, but the second assert fails.
Is there some functionality that I'm missing? Is it possible to do what I want? Is there any reason why what I'm suggesting is particularly bad?
python unit-testing
python unit-testing
asked Mar 25 at 8:34
MultihunterMultihunter
2,16011020
2,16011020
It looks like you actually wantside_effect=[1, 1, 1, 5]
for the get method. Note that you're mocking the class, so the "real result" thatwraps
returns is the unwrapped instance, that's why only__init__
calls are tracked.
– jonrsharpe
Mar 25 at 8:39
This is just a toy example. I want the side effects to be programmatically determined. (i.e. the side_effects are based on the inputs, e.g. a function that is just a switch statement).
– Multihunter
Mar 26 at 2:52
1
A side effect can also be a function, as you only have one method. But your solution below also addresses it, wrapping an instance rather than the class.
– jonrsharpe
Mar 26 at 7:02
add a comment |
It looks like you actually wantside_effect=[1, 1, 1, 5]
for the get method. Note that you're mocking the class, so the "real result" thatwraps
returns is the unwrapped instance, that's why only__init__
calls are tracked.
– jonrsharpe
Mar 25 at 8:39
This is just a toy example. I want the side effects to be programmatically determined. (i.e. the side_effects are based on the inputs, e.g. a function that is just a switch statement).
– Multihunter
Mar 26 at 2:52
1
A side effect can also be a function, as you only have one method. But your solution below also addresses it, wrapping an instance rather than the class.
– jonrsharpe
Mar 26 at 7:02
It looks like you actually want
side_effect=[1, 1, 1, 5]
for the get method. Note that you're mocking the class, so the "real result" that wraps
returns is the unwrapped instance, that's why only __init__
calls are tracked.– jonrsharpe
Mar 25 at 8:39
It looks like you actually want
side_effect=[1, 1, 1, 5]
for the get method. Note that you're mocking the class, so the "real result" that wraps
returns is the unwrapped instance, that's why only __init__
calls are tracked.– jonrsharpe
Mar 25 at 8:39
This is just a toy example. I want the side effects to be programmatically determined. (i.e. the side_effects are based on the inputs, e.g. a function that is just a switch statement).
– Multihunter
Mar 26 at 2:52
This is just a toy example. I want the side effects to be programmatically determined. (i.e. the side_effects are based on the inputs, e.g. a function that is just a switch statement).
– Multihunter
Mar 26 at 2:52
1
1
A side effect can also be a function, as you only have one method. But your solution below also addresses it, wrapping an instance rather than the class.
– jonrsharpe
Mar 26 at 7:02
A side effect can also be a function, as you only have one method. But your solution below also addresses it, wrapping an instance rather than the class.
– jonrsharpe
Mar 26 at 7:02
add a comment |
1 Answer
1
active
oldest
votes
You can use your patch
ed Mock object to return an instance of MagicMock that wraps your mock class by setting that as the return value when the callee tries to instantiate module_a.A
.
class SomeFncTestCase(unittest.TestCase):
@unittest.mock.patch('module_a.A')
def test_it(self, m):
mock_a = MagicMock(wraps=MockA())
m.return_value = mock_a
module_a.some_fnc('in_file')
m.assert_called_with('in_file')
mock_a.get.assert_called()
There is a distinction between m
the Mock that essentially mocks A.__call__
, and mock_a
, a mocked instantiation of the A
class (which provides actual function return values by wrapping an instance of MockA
).
add a comment |
Your Answer
StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55333860%2fpython-unittest-patch-using-custom-mock-class%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
You can use your patch
ed Mock object to return an instance of MagicMock that wraps your mock class by setting that as the return value when the callee tries to instantiate module_a.A
.
class SomeFncTestCase(unittest.TestCase):
@unittest.mock.patch('module_a.A')
def test_it(self, m):
mock_a = MagicMock(wraps=MockA())
m.return_value = mock_a
module_a.some_fnc('in_file')
m.assert_called_with('in_file')
mock_a.get.assert_called()
There is a distinction between m
the Mock that essentially mocks A.__call__
, and mock_a
, a mocked instantiation of the A
class (which provides actual function return values by wrapping an instance of MockA
).
add a comment |
You can use your patch
ed Mock object to return an instance of MagicMock that wraps your mock class by setting that as the return value when the callee tries to instantiate module_a.A
.
class SomeFncTestCase(unittest.TestCase):
@unittest.mock.patch('module_a.A')
def test_it(self, m):
mock_a = MagicMock(wraps=MockA())
m.return_value = mock_a
module_a.some_fnc('in_file')
m.assert_called_with('in_file')
mock_a.get.assert_called()
There is a distinction between m
the Mock that essentially mocks A.__call__
, and mock_a
, a mocked instantiation of the A
class (which provides actual function return values by wrapping an instance of MockA
).
add a comment |
You can use your patch
ed Mock object to return an instance of MagicMock that wraps your mock class by setting that as the return value when the callee tries to instantiate module_a.A
.
class SomeFncTestCase(unittest.TestCase):
@unittest.mock.patch('module_a.A')
def test_it(self, m):
mock_a = MagicMock(wraps=MockA())
m.return_value = mock_a
module_a.some_fnc('in_file')
m.assert_called_with('in_file')
mock_a.get.assert_called()
There is a distinction between m
the Mock that essentially mocks A.__call__
, and mock_a
, a mocked instantiation of the A
class (which provides actual function return values by wrapping an instance of MockA
).
You can use your patch
ed Mock object to return an instance of MagicMock that wraps your mock class by setting that as the return value when the callee tries to instantiate module_a.A
.
class SomeFncTestCase(unittest.TestCase):
@unittest.mock.patch('module_a.A')
def test_it(self, m):
mock_a = MagicMock(wraps=MockA())
m.return_value = mock_a
module_a.some_fnc('in_file')
m.assert_called_with('in_file')
mock_a.get.assert_called()
There is a distinction between m
the Mock that essentially mocks A.__call__
, and mock_a
, a mocked instantiation of the A
class (which provides actual function return values by wrapping an instance of MockA
).
edited Mar 26 at 6:44
jonrsharpe
80.7k11121241
80.7k11121241
answered Mar 26 at 3:48
MultihunterMultihunter
2,16011020
2,16011020
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55333860%2fpython-unittest-patch-using-custom-mock-class%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
It looks like you actually want
side_effect=[1, 1, 1, 5]
for the get method. Note that you're mocking the class, so the "real result" thatwraps
returns is the unwrapped instance, that's why only__init__
calls are tracked.– jonrsharpe
Mar 25 at 8:39
This is just a toy example. I want the side effects to be programmatically determined. (i.e. the side_effects are based on the inputs, e.g. a function that is just a switch statement).
– Multihunter
Mar 26 at 2:52
1
A side effect can also be a function, as you only have one method. But your solution below also addresses it, wrapping an instance rather than the class.
– jonrsharpe
Mar 26 at 7:02