4

This demo function I want to test is pretty straight forward.

def is_email_deliverable(email):
    try:
        return external.verify(email)
    except Exception:
        logger.error("External failed failed")
        return False

This function uses an external service which I want to mock out.

But I can't figure out how to throw an exception from external.verify(email) i.e. how to force the except clause to be executed.

My attempt:

@patch.object(other_module, 'external')
def test_is_email_deliverable(patched_external):    
    def my_side_effect(email):
        raise Exception("Test")

    patched_external.verify.side_effects = my_side_effect
    # Or,
    # patched_external.verify.side_effects = Exception("Test")
    # Or,
    # patched_external.verify.side_effects = Mock(side_effect=Exception("Test"))

    assert is_email_deliverable("some_mail@domain.com") == False

This question claims to have the answer, but didn't work for me.

Ahsanul Haque
  • 9,865
  • 4
  • 35
  • 51

1 Answers1

12

You have used side_effects instead of side_effect. Its something like this

@patch.object(Class, "attribute")
def foo(attribute):
    attribute.side_effect = Exception()
    # Other things can go here

BTW, its not good approach to catch all the Exception and handle according to it.

safwan
  • 353
  • 2
  • 6
  • oh, no. It was a typo. :( Thank u btw. Will accept it. – Ahsanul Haque Feb 04 '18 at 13:11
  • just another thing, can u tell how I can cancel out the `side_effect` after the assertion? I tried to check both `try` and `except` in same function, but `external.verify.return_value` didn't work, because `external.verify.side_effect` is set there already . How can I cancel the `side_effect`? – Ahsanul Haque Feb 04 '18 at 13:17
  • @AhsanulHaque I strongly believe you should test both cases in different test function. But if you would like to do that, you can use context manager for this approach something like [this](https://hastebin.com/voxeguvujo.py) – safwan Feb 04 '18 at 22:11