side_effect 不在 Pytho 中的 Mock 上进行迭代

问题描述 投票:0回答:1

我尝试使用

side_effect
属性通过模拟上的每次调用来获取不同的响应。然而,我每次都会获得第一个。我想问一下我是否可以得到任何帮助。先谢谢你了

import json
from typing import Dict
from unittest.mock import Mock, patch

import requests


def mock_response_1() -> dict:
    return {"data": {"users": [{"id": "AAA"}]}}


def mock_response_2() -> dict:
    return {"data": {"users": [{"id": "BBB"}]}}


def mock_json_response(mocked_json: Dict, status_code: int = 200) -> Mock:
    response_mock = Mock()
    response_mock.configure_mock(**{
        "return_value.status_code": status_code,
        "return_value.headers": {"Content-Type": "application/json"},
        "return_value.json.return_value": mocked_json,
        "return_value.text.return_value": json.dumps(mocked_json),
    })
    return response_mock()


class ApiClient:
    def get_response(self) -> dict:
        request_r = requests.get(url="https://api.test.com")
        request_r = request_r.json()
        return request_r.get("data")


class MockClient(ApiClient):

    @patch('ApiTest.requests.get')
    def get_response(self, mocked_post: Mock):
        mocked_post.side_effect = iter([
            mock_json_response(mock_response_1()),
            mock_json_response(mock_response_2())
        ])
        return super().get_response()


class TestApiClient:
    client = MockClient()

    def test_get_response(self):
        for i in (0, 1):
            print(f"Iteration {i}: {self.client.get_response()}")

结果:

Iteration 0: {'users': [{'id': 'AAA'}]}
Iteration 1: {'users': [{'id': 'AAA'}]}
python python-3.x python-unittest python-unittest.mock
1个回答
0
投票

您的代码副作用迭代器在每次调用 get_response() 时都会重置,导致两次迭代返回相同的响应。

另外,MockClient 的 get_response() 方法应该直接返回模拟响应,而不需要调用父类的方法。调整副作用设置以正确迭代模拟响应,并直接从 MockClient 返回模拟响应。

此代码可以工作

test_api_client.py

import unittest
from ApiTest.api_client import MockClient

class TestApiClient(unittest.TestCase):
    client = MockClient()

    def test_get_response(self):
        for i in range(2):
            print(f"Iteration {i}: {self.client.get_response()}")

if __name__ == '__main__':
    unittest.main()

ApiTest\api_client.py

from typing import Dict
from unittest.mock import Mock, patch
import json
import requests

def mock_response_1() -> dict:
    return {"data": {"users": [{"id": "AAA"}]}}

def mock_response_2() -> dict:
    return {"data": {"users": [{"id": "BBB"}]}}

def mock_json_response(mocked_json: Dict, status_code: int = 200) -> Mock:
    response_mock = Mock()
    response_mock.status_code = status_code
    response_mock.headers = {"Content-Type": "application/json"}
    response_mock.json.return_value = mocked_json
    response_mock.text = json.dumps(mocked_json)
    return response_mock

class ApiClient:
    def get_response(self) -> dict:
        request_r = requests.get(url="https://api.test.com")
        request_r = request_r.json()
        return request_r.get("data")

class MockClient(ApiClient):
    def __init__(self):
        self.mock_responses = [
            mock_response_1(),
            mock_response_2()
        ]
        self.response_index = 0

    @patch('requests.get')
    def get_response(self, mocked_get: Mock):
        mocked_get.return_value = mock_json_response(self.mock_responses[self.response_index])
        self.response_index = (self.response_index + 1) % len(self.mock_responses)
        return super().get_response()

安装依赖项

pip install requests unittest

运行它

python test_api_client.py
Iteration 0: {'users': [{'id': 'AAA'}]}
Iteration 1: {'users': [{'id': 'BBB'}]}

enter image description here

© www.soinside.com 2019 - 2024. All rights reserved.