24

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 = MagickMock() 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?

Syntaxén
  • 465
  • 1
  • 8
  • 15

1 Answers1

23

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!

Alexander Rossa
  • 1,900
  • 1
  • 22
  • 37
Kendas
  • 1,963
  • 13
  • 20