Python 3.x 如何在python中模拟套接字模块?
我正在使用Python 3.x 如何在python中模拟套接字模块?,python-3.x,mocking,raspbian,python-unittest,Python 3.x,Mocking,Raspbian,Python Unittest,我正在使用python3进行一个多播项目,并有一个小程序在本地网络上搜索upnp设备。我想使用unittest和mock对socket.recvfrom(bufsize[,flags])的昂贵调用 这是我的程序/upnp/mucassdp.py: #!/usr/bin/env python3 import socket class ssdpObj(): # Handle Simple Service Discovery Protocol, # for discovering UPnP dev
python3
进行一个多播项目,并有一个小程序在本地网络上搜索upnp
设备。我想使用unittest
和mock
对socket.recvfrom(bufsize[,flags])
的昂贵调用
这是我的程序/upnp/mucassdp.py
:
#!/usr/bin/env python3
import socket
class ssdpObj():
# Handle Simple Service Discovery Protocol,
# for discovering UPnP devices on the local network
def msearch(self):
msg = \
'M-SEARCH * HTTP/1.1\r\n' \
'HOST:239.255.255.250:1900\r\n' \
'ST:upnp:rootdevice\r\n' \
'MX:2\r\n' \
'MAN:"ssdp:discover"\r\n' \
'\r\n'
# Set up UDP socket with timeout and send a M-SEARCH structure
# to the upnp multicast address and port
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
s.settimeout(2)
s.sendto(msg.encode(), ('239.255.255.250', 1900) )
# print received data within the timeout
try:
while True:
# expensive call to mock for testing
data, addr = s.recvfrom(65507)
print (addr, data.decode(), end='')
except socket.timeout:
pass
#!/usr/bin/env python3
import unittest
from unittest.mock import patch
from upnp.mucassdp import ssdpObj
class mucassdpTestCase(unittest.TestCase):
@patch('upnp.mucassdp.socket')
def test_msearch(self, mock_socket):
# instantiate our service
oSsdp = ssdpObj()
mock_socket.recvfrom.return_value = [0, '1']
#mock_socket.recvfrom.side_effect = [0, '1']
oSsdp.msearch()
mock_socket.settimeout.assert_called_with(2)
这是我的测试用例/tests/mucassdpTest.py
:
#!/usr/bin/env python3
import socket
class ssdpObj():
# Handle Simple Service Discovery Protocol,
# for discovering UPnP devices on the local network
def msearch(self):
msg = \
'M-SEARCH * HTTP/1.1\r\n' \
'HOST:239.255.255.250:1900\r\n' \
'ST:upnp:rootdevice\r\n' \
'MX:2\r\n' \
'MAN:"ssdp:discover"\r\n' \
'\r\n'
# Set up UDP socket with timeout and send a M-SEARCH structure
# to the upnp multicast address and port
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
s.settimeout(2)
s.sendto(msg.encode(), ('239.255.255.250', 1900) )
# print received data within the timeout
try:
while True:
# expensive call to mock for testing
data, addr = s.recvfrom(65507)
print (addr, data.decode(), end='')
except socket.timeout:
pass
#!/usr/bin/env python3
import unittest
from unittest.mock import patch
from upnp.mucassdp import ssdpObj
class mucassdpTestCase(unittest.TestCase):
@patch('upnp.mucassdp.socket')
def test_msearch(self, mock_socket):
# instantiate our service
oSsdp = ssdpObj()
mock_socket.recvfrom.return_value = [0, '1']
#mock_socket.recvfrom.side_effect = [0, '1']
oSsdp.msearch()
mock_socket.settimeout.assert_called_with(2)
当我尝试使用以下内容运行测试用例时:
~$ python3 -m unittest tests.mucassdpTest
我收到错误消息(仅相关部分):
我环顾四周,发现了一些类似的问题和答案,例如,使用预期的数据通过构造函数初始化Mock
,添加或设置副作用(我已经尝试过了),但我无法让它在测试中成功运行
在测试条件下,如何设置打补丁的套接字
模块,以从s.recvfrom(…)
获取预期的成对数据,addr
。这里的问题是,您在upnp.mucassdp
中模拟套接字
模块导入,然后尝试用recvfrom()配置它
打电话。但是,recvfrom()
方法存在于socket.socket
类中,而不是socket
模块中
@patch('upnp.mucassdp.socket')
def测试搜索(自模拟插座):
#mock_socket是模块,而不是socket类
解决方法是修补socket.socket
类,然后在测试中,在配置实例之前检索实例
类mucassdpTestCase(unittest.TestCase):
@修补程序('upnp.mucassdp.socket.socket')#修补该类
def测试搜索(自模拟插座):
mock_socket=mock_socket.return_value#我们需要实例
#实例化我们的服务
oSsdp=ssdpObj()
mock_socket.recvfrom.return_value=[0,'1']
#mock_socket.recvfrom.side_effect=[0,'1']
oSsdp.msearch()
mock_socket.settimeout.assert_调用了(2)