[PYTHON] Mock urllib2 and unittest

As a reminder, I got a little stuck when I wrote a test by converting the urllib2.urlopen () to Mock.

Try it first

Code to be tested

Actually, it's a lot of code, but for the sake of simplicity, it looks like the following.

target.py


import urllib2

def get(url):
	return urllib2.urlopen().read()

bad example

This is the first code I wrote easily. There seems to be no problem with one case, but if you execute this, ** the first assertion will pass, but with the second assertion, AssertionError:'hoge'! ='' Will occur and an error ** will occur.

bad_test_sample.py


from nose.tools import *
from mock import Mock
from StringIO import StringIO
import urllib2
import target

def test_get():
    urllib2.urlopen = Mock(return_value=StringIO('hoge'))
	eq_('hoge', target.get("http://dummy-url"))
	eq_('hoge', target.get("http://dummy-url"))

If it is the first time, an error will occur after the second time. ?? ?? It will be. The actual test wouldn't be run twice like this, so it looks like an error at an apparently strange timing. At least that was my time.

Correct example

The bottom line is that ** "requires read-> make with StringIO" is wrong **, so don't do that and just use Mock.

good_test_sample.py


from nose.tools import *
from mock import Mock
import urllib2
import target

def test_get():
    urllib2.urlopen = Mock()
	urllib2.urlopen.return_value.read.return_value = 'hoge'
	eq_('hoge', target.get("http://dummy-url"))
	eq_('hoge', target.get("http://dummy-url"))

Commentary

If you pass it with StringIO, it will certainly come with a proper read () method, but on the contrary, because it is proper, ** the same stream will be referenced in the second and subsequent executions, and the pointer is already at the end * *. So, after the second time, read () does not give anything. After all, the area around the pointer is a must for programmers.

Recommended Posts

Mock urllib2 and unittest
mock
Use Mock with pytest
Tested with boto3 + mock
Mock urllib2 and unittest
Touch the mock and stub
[Python] Test sample using unittest2, mock
unittest
Common mock by moto in Python Unittest