如何使用标准模拟库模拟urllib2

时间:2016-01-04 09:55:09

标签: python unit-testing mocking

我遇到了与Mocking urllib2.urlopen().read() for different responses

类似的问题

但解决方案不适合我。

当我想模拟urlopen对象时,我的模拟对象总是返回<MagicMock name='urlopen().read()' id='140016097869776'>

这是我要测试的内容,mod.py

import urllib2
from zipfile import ZipFile
from io import BytesIO
def verify(url, checksum):
    try:
        conn = urllib2.urlopen(url)
        byte = conn.read()
        conn.close()           
        myzip = ZipFile(BytesIO(byte))
    except Exception as e:
        err = get_error(400, "Not a valid zip format: %s" % (str(e)))
        return Response(err, status=status.HTTP_400_BAD_REQUEST)
    return byte

这是我模仿的内容

@mock.patch('mod.urllib2.urlopen')
@mock.patch('mod.ZipFile')
@mock.patch('mod.BytesIO')
def test_verify(self, urlopen_mock, zipfile_mock, bytesio_mock):
    conn = mock.Mock()
    conn.read.return_value = 'byte'
    urlopen_mock.return_value = conn
    zf = mock.Mock()
    zipfile_mock.return_value = zf
    assertEqual(verify('url','checksum'), 'byte')

但是,在我模拟时,返回的字节总是<MagicMock name='urlopen().read()' id='140016097869776'>,而不是'byte'

我想念一些重要的事情吗?

1 个答案:

答案 0 :(得分:1)

您需要在conn:

的返回值上定义read
conn.return_value.read.return_value = 'byte'

编辑我误解了这个问题。实际问题是方法参数以相反的顺序传递给装饰器的应用方式:所以你的签名应该是:

def test_verify(self, bytesio_mock, zipfile_mock, urlopen_mock):