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;








0















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?










share|improve this question






















  • 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






  • 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

















0















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?










share|improve this question






















  • 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






  • 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













0












0








0








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?










share|improve this question














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






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Mar 25 at 8:34









MultihunterMultihunter

2,16011020




2,16011020












  • 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






  • 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












  • 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












1 Answer
1






active

oldest

votes


















0














You can use your patched 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).






share|improve this answer



























    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
    );



    );













    draft saved

    draft discarded


















    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









    0














    You can use your patched 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).






    share|improve this answer





























      0














      You can use your patched 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).






      share|improve this answer



























        0












        0








        0







        You can use your patched 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).






        share|improve this answer















        You can use your patched 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).







        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited Mar 26 at 6:44









        jonrsharpe

        80.7k11121241




        80.7k11121241










        answered Mar 26 at 3:48









        MultihunterMultihunter

        2,16011020




        2,16011020





























            draft saved

            draft discarded
















































            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.




            draft saved


            draft discarded














            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





















































            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







            Popular posts from this blog

            Kamusi Yaliyomo Aina za kamusi | Muundo wa kamusi | Faida za kamusi | Dhima ya picha katika kamusi | Marejeo | Tazama pia | Viungo vya nje | UrambazajiKuhusu kamusiGo-SwahiliWiki-KamusiKamusi ya Kiswahili na Kiingerezakuihariri na kuongeza habari

            Swift 4 - func physicsWorld not invoked on collision? The Next CEO of Stack OverflowHow to call Objective-C code from Swift#ifdef replacement in the Swift language@selector() in Swift?#pragma mark in Swift?Swift for loop: for index, element in array?dispatch_after - GCD in Swift?Swift Beta performance: sorting arraysSplit a String into an array in Swift?The use of Swift 3 @objc inference in Swift 4 mode is deprecated?How to optimize UITableViewCell, because my UITableView lags

            Access current req object everywhere in Node.js ExpressWhy are global variables considered bad practice? (node.js)Using req & res across functionsHow do I get the path to the current script with Node.js?What is Node.js' Connect, Express and “middleware”?Node.js w/ express error handling in callbackHow to access the GET parameters after “?” in Express?Modify Node.js req object parametersAccess “app” variable inside of ExpressJS/ConnectJS middleware?Node.js Express app - request objectAngular Http Module considered middleware?Session variables in ExpressJSAdd properties to the req object in expressjs with Typescript