3

I have an object method which changes an attribute of an object. Another method (the one I'm trying to test) calls the first method multiple times and afterward uses the attribute that was modified. How can I test the second method while explicitly saying how the first method changed that attribute?

For example:

def method_to_test(self):
    output = []
    for _ in range(5):
        self.other_method()
        output.append(self.attribute_changed_by_other_method)
    return output

I want to specify some specific values that attribute_changed_by_other_method will become due to other_method (and the real other_method uses probabilities in deciding on how to change attribute_changed_by_other_method).

I'm guessing the best way to do this would be to "mock" the attribute attribute_changed_by_other_method so that on each time the value is read it gives back a different value of my specification. I can't seem to find how to do this though. The other option I see would be to make sure other_method is mocked to update the attribute in a defined way each time, but I don't know of a particularly clean way of doing this. Can someone suggest a reasonable way of going about this? Thank you much.

2 Answers 2

2

What you can actually do is use flexmock for other_method. What you can do with flexmock is set a mock on an instance of your class. Here is an example of how to use it:

class MyTestClass(unittest.TestCase):
    def setUp(self):
        self.my_obj = MyClass()
        self.my_obj_mock = flexmock(self.my_obj)

    def my_test_case(self):
        self.my_obj_mock.should_receive('other_method').and_return(1).and_return(2).and_return(3)
        self.my_obj.method_to_test()

So, what is happening here is that on your instance of MyClass, you are creating a flexmock object out of self.my_obj. Then in your test case, you are stating that when you make your call to method_to_test, you should receive other_method, and each call to it should return 1, 2, 3 respectively.

Furthermore, if you are still interested in knowing how to mock out attribute_changed_by_other_method, you can use Mock's PropertyMock:

Hope this helps. Let me know how it goes!

Sign up to request clarification or add additional context in comments.

1 Comment

The PropertyMock got me what I was looking for (using the type() approach given in the link you posted for it).
1

For anyone still looking for a straightforward answer, this can be done easily with PropertyMock as the accepted answer suggests. Here is one way to do it.

from unittest.mock import patch, PropertyMock


with patch("method_your_class_or_method_calls", new_callable=PropertyMock) as mock_call:
        mock_call.side_effect = [111, 222]
        class_or_method()

Each subsequent call of that patched method will return that list in sequence.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.