2

I have written a code in views.py

def fun():
    try:
         --Do some operation--
    except OSError:
         --Do something else-- 

And I have written a test case to cover total functionality of the code. To test the "except" part I have written the following code where it will raise "OSError",

with pytest.raises(OSError):
    response = client.post(reverse('my_views_funurl'), follow=True)

But, I am getting this error

response = client.post(reverse('my_views_funurl'), follow=True)
E           Failed: DID NOT RAISE

How to raise "OSError" to cover the except part in test cases. By the way I am using django-framework

Chanda Korat
  • 2,453
  • 2
  • 19
  • 23
  • you can operate on a file that doesnt exist that will give you oserror ex: os.remove('file') but file doesnt exist. – Anand Tripathi Mar 07 '17 at 09:08
  • You mock the function that should raise the exception and give the exception as side effect. https://docs.python.org/3/library/unittest.mock.html#quick-guide – Klaus D. Mar 07 '17 at 09:09

2 Answers2

0

Best thing would probably be to just mock the method to throw the exception you need, instead of going through all the trouble of actually creating conditions in which OSError would be thrown. A toy example:

from unittest.mock import Mock

def something():
    ...

something = Mock(side_effect=OSError('Your error text'))

>>> something()
>>> Traceback (most recent call first):
>>> ...
>>> OSError: Your error text

Now as I said, it's only a toy example, so for your own project with different structure and all you will most likely need a bit different setup (given the information you provided it's hard to know how exactly it will look). For example, if you're expecting that some call will throw an OSError exception inside your fun(), then you will need to mock the call in the module fun() is located in. Good places to start reading up on mocks:

  1. Docs quick guide
  2. Patch documentation (pay particularly close attention to 'where to patch' part)
  3. Useful in-depth example on stack-overflow. As it is a bit more sophisticated than my proof-of-concept example, it will probably resemble what you're trying to achieve.
cegas
  • 2,823
  • 3
  • 16
  • 16
  • I am getting the following error: with pytest.raises(OSError): > response = client.post(reverse('hard_delete_drive', kwargs = {'slug':doc.slug}), follow=True) E Failed: DID NOT RAISE –  Mar 10 '17 at 05:12
  • What method exactly should throw the exception you are expecting? Is it `hard_delete_drive()`, or something inside the view? What module is it in? – cegas Mar 10 '17 at 05:38
  • `hard_delete_drive()`is a function in views.py and I used try-except method to catch the errors. I am catching `OSError` and `IOError` in this function. I want to write a test to cover the lines uner `OSError` and `IOError`. For that I am raising error using `with pytest.raises(IOError):` but I am getting `DID NOT RAISE`. –  Mar 10 '17 at 06:04
  • 1
    Which method calls in `hard_delete_drive()` are susceptible to `OSError`/`IOError`? You will most likely need to mock them. Could you edit your original question to include them, so that I could attempt to reproduce what you're trying to achieve on my machine? – cegas Mar 10 '17 at 09:38
  • The question is about "pytest" not "unittests". – Juanmi Taboada Apr 10 '23 at 06:48
  • 1
    There's nothing preventing you from using `unittest.mock` (included in standard Python library) along with `pytest` if you so wish. As far as I know, `mocker` that you use in your answer comes from `pytest-mock` package, which itself is a thin wrapper around `mock` package (included in Python 3.3 onwards as `unittest.mock`). Since using `pytest` doesn't necessarily imply using `pytest-mock` and the question did not mention `mocker`, my answer relies on tools included in standard Python installation. – cegas Apr 10 '23 at 19:20
0

The right way to do this with "pytest" would be to provide the "side_effect" parameter to patch() with your expected Exception. Example:

def your_test_function(mocker):
    mocker.patch(
        "function.being.mocked",
        side_effect=OSError()
    )
    with pytest.raises(OSError):
        function.being.mocked()
Juanmi Taboada
  • 539
  • 10
  • 25