【问题标题】:How to mock socket module in python?如何在python中模拟socket模块?
【发布时间】:2018-04-05 00:22:22
【问题描述】:

我正在使用python3 进行多播项目,并且有一个小程序可以在本地网络上搜索upnp 设备。我想使用unittestmocksocket.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

这是我的测试用例./tests/mucassdpTest.py

#!/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

我收到错误消息(仅相关部分):

ERROR: test_msearch (tests.mucassdpTest.mucassdpTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/ingo/devel/muca-tools/upnp/mucassdp.py", line 27, in msearch
    data, addr = s.recvfrom(65507)
ValueError: not enough values to unpack (expected 2, got 0)

我环顾四周,发现了一些类似的问题和答案,例如通过其构造函数初始化Mock,使用预期的data, addr 或设置side_effect(我已经尝试过),但我的测试无法让它成功运行。

在测试条件下,如何设置已修补的socket 模块以从s.recvfrom(...) 获得预期的配对data, addr

【问题讨论】:

    标签: python-3.x mocking raspbian python-unittest


    【解决方案1】:

    这里的问题是您正在模拟upnp.mucassdp 中的socket 模块导入,然后尝试使用recvfrom() 调用对其进行配置。但是,recvfrom() 方法存在于 socket.socket 类上,而不是 socket 模块上。

    @patch('upnp.mucassdp.socket')
    def test_msearch(self, mock_socket):
        # mock_socket is the module, not the socket class
    

    解决的方法是给socket.socket类打补丁,然后在测试中,在配置之前检索实例。

    class mucassdpTestCase(unittest.TestCase):
    
        @patch('upnp.mucassdp.socket.socket')  # Patch the class
        def test_msearch(self, mock_socket):
            mock_socket = mock_socket.return_value  # We want the instance
    
            # 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)
    

    【讨论】:

      猜你喜欢
      • 2021-12-28
      • 2021-08-31
      • 2017-05-04
      • 1970-01-01
      • 1970-01-01
      • 2018-12-05
      • 1970-01-01
      相关资源
      最近更新 更多