我尝试在python中使用超时异常模拟 socket 并拥有这个小测试程序:

#!/usr/bin/env python3

import socket

class SocketToutClass():

    def socket_timeout(self):
        """Set up UDP socket with timeout"""

        sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
        sock.settimeout(2)
        cnt = sock.sendto(b'hello world', ('239.255.255.250', 1900))
        print('sent', cnt, 'bytes')
        try:
            while True:
                data = sock.recv(4096)
                print(data.decode(), end='')
        except socket.timeout:
            print('timed out')
        except KeyboardInterrupt:
            pass

if __name__ == "__main__":
    oTout = SocketToutClass()
    oTout.socket_timeout()

运行它我得到这个输出:

~$ python3 socket_tout.py
sent 11 bytes
timed out
~$

我读了Raising exceptions with mocks

一个有用的属性是side_effect . 如果将其设置为异常类或实例,则在调用mock时将引发异常 .

现在我模拟它包括超时异常:

#!/usr/bin/env python3

import unittest
from unittest.mock import patch

from socket_tout import SocketToutClass

class socket_timeoutTestCase(unittest.TestCase):

    @patch('socket_tout.socket.socket')     # Patch the class
    def test_socket_timeout(self, mock_socket):
        oMock_socket = mock_socket.return_value   # we want the instance
        # set up our service and instantiate it
        oMock_socket.sendto.return_value = 11
        oMock_socket.recv.return_value = b'data\r\n'
        oMock_socket(side_effect=Exception('timeout'))
        oTout = SocketToutClass()
        oTout.socket_timeout()

运行测试我得到无限输出而没有超时:

~$ python3 -m unittest socket_toutTest.py
sent 11 bytes
data
data
data
...

我做错了什么?为什么超时异常不会引发?