如何通过模拟库模拟套接字对象
问题描述:
如何通过mock库(在Python 3的情况下为unittest.mock
)从Python标准库中模拟socket
的TCPSocket
包装?如何通过模拟库模拟套接字对象
这是我的包装:
import socket
import utils
class TCPSocket:
def __init__(self):
self.buf = ''
def __enter__(self):
pass
def __exit__(self, exc_type, exc_val, exc_tb):
self.close()
def connect(self, host, port):
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.sock.connect((host, port))
def close(self):
self.sock.close()
def send(self, data):
self.sock.send(data)
def sendall(self, data):
self.sock.sendall(data)
# For best match with hardware and network realities,
# the value of limit should be a relatively small power of 2, for example, 4096
def recv_some(self, limit=4096):
return self.sock.recv(limit)
def recv_bytes(self, count):
while len(self.buf) < count:
self.buf += self.recv_some()
parts = utils.split_first_n(self.buf, count)
self.buf = parts[1]
return parts[0]
def recv_until(self, delim):
while delim not in self.buf:
self.buf += self.recv_some()
parts = self.buf.split(delim, maxsplit=1)
self.buf = parts[1]
return parts[0]
我想测试就像recv_until和recv_bytes功能是否做什么,他们真正需要的。
答
它可以简单到
import mock # or from unittest import mock
mock_socket = mock.Mock()
mock_socket.recv.return_value = data
然后使用mock_socket
,你会用真正的插座。您也可以模拟创建套接字的任何内容,以根据您的需要返回模拟值,如此处配置的模拟值。
对于你的情况,你可以嘲笑socket.socket
,以便它返回的东西,其方法可以配置。请注意,本例中的mock_socket
是返回Socket
对象的函数,而不是Socket
对象本身。
with mock.patch('socket.socket') as mock_socket:
mock_socket.return_value.recv.return_value = some_data
t = TCPSocket()
t.connect('example.com', 12345) # t.sock is a mock object, not a Socket
self.assertEqual(t.recv_bytes(), whatever_you_expect)
t.sock.connect.assert_called_with(('example.com', 12345))
我不完全理解如何使用这个模拟对象。我使用方法'connect'和'recv_some'从Python的标准库'TCPSocket'中为'socket'封装。那我该怎么办? – FrozenHeart
你真的需要模拟'socket',还是你需要模拟'TCPSocket'实例?请使用您需要的确切场景编辑您的问题:使用模拟对象,输入和预期输出的代码。 – chepner
http://pastie.org/10814947我想测试像'recv_until'和'recv_bytes'这样的函数是否真的需要 – FrozenHeart