You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

单元测试Mock Twilio API时触发TypeError:'list'对象不可调用

问题:Twilio API单元测试Mock时触发TypeError

我开发了通过Twilio API获取Flow系统信息的FlowChecker类,业务代码运行正常,但单元测试Mock API时触发错误。测试代码中先将mock_client.studio.v2.flows设为列表,后续调用mock_client.studio.v2.flows(mock_flow.sid)时抛出TypeError: 'list' object is not callable,已搜索相关问题未找到解决方案,请求帮助。

业务代码

from twilio.rest import Client


class FlowChecker:

    def __init__(self, twilio_sid, twilio_auth_token):
        self.twilio_SID = twilio_sid
        self.twilio_auth_token = twilio_auth_token
        self.client = Client(self.twilio_SID, self.twilio_auth_token)

        self.calls = self.client.calls.list()
        self.flows = self.client.studio.v2.flows

    def get_active_executions(self):
        active_executions = []
        for flow in self.flows.list():
            executions = self.client.studio.v2.flows(flow.sid).executions.list()
            for execution in executions:
                if execution._properties['status'] != 'ended':
                    active_executions.append({'flow_sid': flow.sid, 'execution': execution})

测试代码(原错误版本)

import unittest
from unittest.mock import Mock, patch
from flows.twilio_flows import FlowChecker

class FlowCheckerTest(unittest.TestCase):


    @patch('flows.twilio_flows.Client')
    def test_get_active_flows(self, mock_client):
        flow_checker = FlowChecker('fake_sid', 'fake_auth_token')
        mock_call = Mock()
        mock_flow = Mock()
        mock_flow.sid = 0
        mock_execution = Mock()
        mock_execution._properties = {'status': 'ended'}
        mock_client.calls.list().return_value = [mock_call]
        mock_client.studio.v2.flows = [mock_flow]
        mock_client.studio.v2.flows(mock_flow.sid).executions.list().return_value = [mock_execution]
        self.assertEqual(flow_checker.get_active_executions(), [])

错误栈

Ran 2 tests in 0.045s

FAILED (errors=1)

Error
Traceback (most recent call last):
  File "C:\Users\Devon\AppData\Local\Programs\Python\Python310\lib\unittest\mock.py", line 1369, in patched
    return func(*newargs, **newkeywargs)
  File "C:\Users\Devon\PycharmProjects\Day_35\tests\twilio_flows_test'.py", line 19, in test_get_active_flows_when_empty
    mock_client.studio.v2.flows(mock_flow.sid).executions.list().return_value = [mock_execution]
TypeError: 'list' object is not callable


Process finished with exit code 1

错误分析

你将mock_client.studio.v2.flows直接赋值为列表[mock_flow],但Twilio的flows对象实际具备双重特性:既是可调用对象(通过flows(sid)获取单个flow),又拥有.list()方法获取flow列表。列表属于不可调用类型,执行flows(mock_flow.sid)时自然触发类型错误。

修正后的测试代码

import unittest
from unittest.mock import Mock, patch
from flows.twilio_flows import FlowChecker

class FlowCheckerTest(unittest.TestCase):

    @patch('flows.twilio_flows.Client')
    def test_get_active_flows(self, mock_client):
        # 初始化模拟对象
        mock_call = Mock()
        mock_flow = Mock()
        mock_flow.sid = 0
        mock_execution = Mock()
        mock_execution._properties = {'status': 'ended'}

        # 配置calls的返回值
        mock_client.calls.list.return_value = [mock_call]

        # 创建flows的Mock对象,同时支持调用和list方法
        mock_flows = Mock()
        mock_flows.list.return_value = [mock_flow]
        
        # 配置flows(sid)返回的对象,包含executions属性
        mock_single_flow = Mock()
        mock_single_flow.executions.list.return_value = [mock_execution]
        mock_flows.return_value = mock_single_flow

        # 将mock_flows赋值给client.studio.v2.flows
        mock_client.studio.v2.flows = mock_flows

        # 初始化FlowChecker并执行测试
        flow_checker = FlowChecker('fake_sid', 'fake_auth_token')
        self.assertEqual(flow_checker.get_active_executions(), [])

关键修正点

  1. 用Mock()创建mock_flows对象,替代直接赋值列表
  2. 给mock_flows.list设置返回值,对应业务代码中self.flows.list()的调用
  3. 创建mock_single_flow模拟单个flow对象,配置其executions.list的返回值,再让mock_flows()(调用时)返回这个对象,匹配业务代码中flows(flow.sid).executions.list()的逻辑

内容的提问来源于stack exchange,提问作者Devon Hume

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 08:15:28