Mocking a python class that changes an instance variable after a method call?

I have code in which a method call update()changes the values ​​of some instance variables. I use the modified value to leave a loop. Here is a simplified example of my code:

def do_stuff(self):
    # get a new instance of A
    a = get_a()
    while True:
        a.update()
        if a.state == 'state':
            break

This is a simple version of the class (I cannot change the class because it is a third-party library):

class A(object):
    def __init__(self):
        self.state = ''

    def update(self):
        # call to external system
        self.state = extern_func()

Now I want to test my function do_stuff()by mocking class A. To test every aspect of the function, I want to have all the different values state, and it should change after each call a.update()(repeat according to different states).

I started with this setup for my unit test:

from mock import Mock, patch
import unittest

class TestClass(unittest.TestClass):

    @patch('get_a')
    def test_do_stuff(self, mock_get_a):
         mock_a = Mock(spec=A)
         mock_get_a.return_value = mock_a

         # do some assertions

Mock? , Mock side_effect, . ?

+4
1

:

from mock import Mock, MagicMock, patch

sep = '***********************\n'

# non-mock mocks
def get_a():
    return A()
def extern_func():
    return 'foo'

def do_stuff(self):
    # get a new instance of A
    a = get_a()
    while True:
        a.update()
        print a.state
        if a.state == 'state':
            break

class A(object):
    def __init__(self):
        self.state = ''

    def update(self):
        # call to external system
        self.state = extern_func()

@Simeon Viser, extern_func:

print sep, 'patch extern'
mock = MagicMock(side_effect = [1,2,3,4, 'state'])
@patch('__main__.extern_func', mock)
def foo():
    do_stuff(3)
foo()

>>> 
***********************
patch extern
1
2
3
4
state

side_effect , A.update auto_spec = True.

:

print sep, 'patch update context manager call do_stuff'
def update_mock(self):
    self.state = mock()
mock = MagicMock(side_effect = [1,2,3,4, 'state'])
with patch.object(A, 'update', autospec = True) as mock_update:
    mock_update.side_effect = update_mock
    do_stuff(3)

>>>
***********************
patch update context manager call do_stuff
1
2
3
4
state

:

print sep, 'patch update decorator test_do_stuff'
def update_mock(self):
    self.state = mock()
mock = MagicMock(side_effect = [1,2,3,4, 'state'])
@patch.object(A, 'update', autospec = True, side_effect = update_mock)
def test_do_stuff(self):
    do_stuff(3)
test_do_stuff()

>>>
***********************
patch update decorator test_do_stuff
1
2
3
4
state

: , , , , , . Edits .

+1

All Articles