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: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.