Locked learning resources

Join us and get access to thousands of tutorials and a community of expert Pythonistas.

Unlock This Lesson

Locked learning resources

This lesson is for members only. Join us and get access to thousands of tutorials and a community of expert Pythonistas.

Unlock This Lesson

Using Mock Instead

00:00 In the previous lesson, you’ve seen how using io.StringIO objects can be useful for testing some kind of functions like the one we’ve had initially where the input argument is a file-like object.

00:13 But what if you have a function that takes a path as an input and then there’s the handling of opening that file and reading it, etc, inside of the body of the function.

00:23 In that case, if you passed a StringIO object in here, of course that wouldn’t work because then you’d be calling open() on a StringIO object and that messes things up, right?

00:33 We can try it out quickly in the console.

00:40 I am going to create another StringIO object. I’ll just call it ff for fake file.

00:47 StringIO

00:50 and we’re getting ever shorter. It’s just saying “hi” now. And now essentially it would be the equivalent of doing something like that, that you pass the StringIO object to open() and then of course you get an error. In this case, it’s a TypeError that tells you it needs string, bytes, or path-like objects and not a StringIO object.

01:15 So with a function like that, that takes a path as an input, you couldn’t test it in the same way that you just did before, and using StringIO objects actually is no help in that case.

01:25 What you will need to do instead is use mocking to replace the functionality of the open() function. And you can do that like so. I wrote a short function that shows you how to do that.

01:38 So the first one seen before, that’s the one that tests the original upcase_file_content() function.

01:45 And now I’m also importing upcase_file_content() from path. And down here you can see the way that you can test such a function.

01:53 So you would use from unittest.mock you would import patch and mock_open. In that case, because mocking the open() function is such a useful and common thing to do, there’s actually a built-in mock_open that you can use as a replacement callable.

02:08 And you would use the patch decorator, tell it that you want to patch the open() function from the built-ins and then instead replace it with the mock_open function that you imported from unittest.mock.

02:20 And then you also tell it that that data that’s going to be in there that is basically going to read will be “HELLO, WORLD” in that case. And then here we have our test function that takes a self and a mock_file as an input and then calls upcase_file_content() from path with a “dummy_path” so this could be anything, right?

02:40 And then asserts equal that the result from calling this function with a “dummy_path” with the patched open() function is going to return HELLO, WORLD exclamation mark capitalized, right?

02:53 And then you’re also using a method on the mock object called assert_called_once_with() to just confirm that the function was called once with dummy_path and r as the inputs.

03:05 Now when you go ahead and say python -m unittest and run this file again, you can see that both tests, both of these tests pass.

03:15 So both the one where you use StringIO object as an input to the function that expects a file-like object as an input and also the other test function where you needed to mock the open() function in order to pass it where yeah, the StringIO object is of no help.

03:36 Okay, so this just as an end side note to this short story about how you can mimic a file object on disk in memory using StringIO. And then with this short reminder that this only works for testing, if the function that you’re working with takes a file object as an input, then you can use it for testing.

03:55 Otherwise you’re going to have to work around it using mocking.

Become a Member to join the conversation.