viggo
viggo

Reputation: 536

Mock a method of a mocked object in Python?

I am writing unit tests for a project written in Python 3.4, using the unittest.mock library. The function I am testing contains a call to a function

versions = get_all_versions(some_argument)

which I have patched with a MagicMock object that returns a list, so that version becomes a list of version numbers, which all works fine.

Now, the code I am testing has changed a bit, and looks like

versions = get_all_versions(some_argument).order_by(another_argument)

Now I need the order_by method to return the same list of version numbers, while get_all_versions should remain mocked, and I have some problems achieving this.

I have tried patching it with

get_all_versions = MagicMock()
get_all_versions.order_by = version_list

but that does not work, and I guess it is because order_by is a method and not a property. I have also tried

get_all_versions = MagicMock()
get_all_versions.order_by = MagicMock(return_value=version_list)

and (more desperately)

get_all_versions = MagicMock(return_value=MagicMock(return_value=version_list))

but neither of those two work.

How do I mock a function that returns an object, and then mock a method of that object so that it returns a list?

Upvotes: 31

Views: 18144

Answers (1)

Kendas
Kendas

Reputation: 2253

What you want is to have get_all_versions return an object that has a method order_by which returns version_list:

get_all_versions = MagicMock()
get_all_versions.return_value.order_by.return_value = version_list

To explain why your attempts didn't work, your first attempt replaces the method order_by with the value version_list:

get_all_versions = MagicMock()
get_all_versions.order_by = version_list

The result of this is roughly this:

get_all_versions.order_by == version_list

The second attempt replaces the return value of get_all_versions with something that looks like a function and returns version_list:

get_all_versions = MagicMock(return_value=MagicMock(return_value=version_list))

This results in:

get_all_versions(some_argument)(another_argument) == version_list

I hope this clears things up!

Upvotes: 29

Related Questions