As a reminder, I got a little stuck when I wrote a test by converting the urllib2.urlopen () to Mock.
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()
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.
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"))
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.