3

In unittest I can assert to side_effect iterable with values - each of them one-by-one will be returned when patched method called, moreover I found that in unittest my patched method can return different results according to input arguments. Can I make something like that in pytest? Documentation does not mention this.

Community
  • 1
  • 1
Vitaly Zdanevich
  • 13,032
  • 8
  • 47
  • 81

2 Answers2

7

You can use Mock's side_effect parameter to set what is to be returned for each call.

side_effect: A function to be called whenever the Mock is called. See the side_effect attribute. Useful for raising exceptions or dynamically changing return values. The function is called with the same arguments as the mock, and unless it returns DEFAULT, the return value of this function is used as the return value. Alternatively side_effect can be an exception class or instance. In this case the exception will be raised when the mock is called. If side_effect is an iterable then each call to the mock will return the next value from the iterable. A side_effect can be cleared by setting it to None.

For instance:

return_data = [3, 5]
test_mock = Mock(side_effect=return_data)
monkeypatch.setattr(your_module, "some_func", test_mock)

This way first time your call calls "some_func" it will return 3 and when you call it a second time it will return 5

Then you can if it was called twice

assert test_mock.call_count == len(return_data)

return data should be Iterable (list, set, tuple) and can contain anything you would like (int, string, object, tuples, lists, ...)

Vlad Bezden
  • 83,883
  • 25
  • 248
  • 179
1

You could certainly monkeypatch something with a class with a __call__ attribute which does whatever you want - however, nothing keeps you from using unittest.mock with pytest - there's even the pytest-mock plugin to make this easier.

The Compiler
  • 11,126
  • 4
  • 40
  • 54