How do you change the result of mocking methods using the Mock framework?

I have a module like the following:

'''example.py'''
from some.module import Session

def init_system():
    var_one = Session.query(SQLAModelA).all()
    var_two = [(x.attr_B_a, x) for x in Session.query(SQLAModelB).all()]

    for value in var_one:
        something = value.attr_A_a + value.attr_A_c
    # Will do something with var_two etc (which has different attributes)
    something_else = [x.attr_B * 2 for x in var_two]
    return result

      

Session refers to the SQLAlchemy session handler that is negotiating with the DB. For testing purposes, I need to be able to mock the request method in a Session object (or maybe just a Session object?), So I can test init_system

without interacting with the database. How do I use the Mock framework to do this?

Indeed the bit that puzzles me is, if I mock a method query()

, how can I change the output of its entire class-specific method that is passed to query()

??

I hope I can do something like:

def test_init_numbers():
    import
    my_mock_object = MagicMock()
    with patch('some.module.Session.query', my_mock_object):
        result = example.init_system()
        assert result == ['expected', 'result']

      

However, I don't know what I need to do for my_mock_object

it to simulate correctly query()

. I assume he needs to implement a method all()

that returns an iterator. And I know that I could create some more mock objects for this returned iterator, making sure they have values ​​for the appropriate attributes, like this:

var_one_element_mock = MagicMock(spec=SQLAModelA)
var_one_element_mock.attr_A_a = 12

var_two_element_mock = MagicMock(spec=SQLAModelB)
var_one_element_mock.attr_B = 100

      

And of course, I can create iterations of different versions of these MagicMock

objects, which can be used by the init_system function, for example in a string for value in var_one

.

But I don't know how to put all the mocked objects together, so I can just mock the method Session.query

given that it is being passed a class to it that affects the contents of the returned iterative file.

Thank!

+3


source to share


1 answer


I don't know if you need help, but if you want to control what happens when the MagicMock object is called, you can pass a function as the side_effect argument. Something like this should work.



def test_init_numbers():
    import
    my_mock_object = MagicMock()
    def return_iterator():
      ## create and return your iterator here

    my_mock_object.all = MagicMock(side_effect=return_iterator)
    with patch('some.module.Session.query', my_mock_object):
        result = example.init_system()
        assert result == ['expected', 'result']

      

0


source







All Articles