使用模拟引发异常的测试

2024-06-09 08:54:19 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个奇怪的错误,我无法理解。我试图测试一个方法是否在另一个方法中调用。我在PyCharm上使用了调试器,但似乎测试失败了,因为调用第二个函数会引发异常

test.py

def test_reply_to_toot(self, directory):
    with patch("mastodon.Mastodon") as mastodon_mock:
        mastodon_mock.return_value = Mock()
        mastodon_mock.status_post.assert_called_with(bot.reply_to_toot("1", account_name="@fake", message="test"))

bot.py(正在测试的方法)

#   Set up Mastodon
mastodon = Mastodon(
    access_token=os.getenv("ACCESS_TOKEN"),
    api_base_url=settings.BASE_ADDRESS
)
    def reply_to_toot(post_id, account_name, message=None, status_notifications=None):
        media_ids = []
        for fn in os.listdir(str(settings.INPUT_FOLDER)):
            if fn.endswith(('.jpeg', '.png')):
                print(Path(fn))
                image_dict = mastodon.media_post(str(settings.INPUT_FOLDER / fn))
                media_ids.append(image_dict["id"])
        if message is not None:
            parts = []
            total_len = str(len(message) // settings.MAX_MESSAGE_LENGTH + 1)
            count = 1
            split_lines = message.splitlines(True)
            while split_lines:
                message_part = "@" + account_name + " {}/".format(count) + total_len + "\n\n"
                while split_lines != [] and len(message_part) + len(split_lines[0]) < settings.MAX_MESSAGE_LENGTH:
                    message_part += split_lines[0]
                    split_lines = split_lines[1:]
                parts.append(message_part)
                count += 1
            for part in parts:
                print(part)
                post_id = mastodon.status_post(status=part, media_ids=media_ids, in_reply_to_id=post_id)
        else:
            while media_ids:
                mastodon.status_post(status=message, media_ids=media_ids[0:4], in_reply_to_id=post_id)
                media_ids = media_ids[4:]

提出的例外情况:

Error
Traceback (most recent call last):
  File "C:\Python35\lib\unittest\case.py", line 58, in testPartExecutor
    yield
  File "C:\Python35\lib\unittest\case.py", line 600, in run
    testMethod()
  File "C:\Python35\lib\unittest\mock.py", line 1157, in patched
    return func(*args, **keywargs)
  File "C:\Users\Hugh\PycharmProjects\summer-project\test\test.py", line 70, in test_reply_to_toot
    mastodon_mock.status_post.assert_called_with(bot.reply_to_toot("1", account_name="@fake", message="test"))
  File "C:\Users\Hugh\PycharmProjects\summer-project\src\bot.py", line 65, in reply_to_toot
    post_id = mastodon.status_post(status=part, media_ids=media_ids, in_reply_to_id=post_id)
  File "<decorator-gen-60>", line 2, in status_post
  File "C:\Users\Hugh\PycharmProjects\summer-project\venv\lib\site-packages\mastodon\Mastodon.py", line 102, in wrapper
    return function(self, *args, **kwargs)
  File "C:\Users\Hugh\PycharmProjects\summer-project\venv\lib\site-packages\mastodon\Mastodon.py", line 1776, in status_post
    return self.__api_request('POST', '/api/v1/statuses', params, headers = headers, use_json = use_json)
  File "C:\Users\Hugh\PycharmProjects\summer-project\venv\lib\site-packages\mastodon\Mastodon.py", line 3429, in __api_request
    error_msg)
mastodon.Mastodon.MastodonNotFoundError: ('Mastodon API returned error', 404, 'Not Found', 'The status you are trying to reply to does not appear to exist.')


Assertion failed

Assertion failed

Ran 1 test in 0.146s

FAILED (errors=1)

Process finished with exit code 1

Assertion failed

Assertion failed

Assertion failed

Assertion failed

Tags: toinpytestididsmessagestatus
1条回答
网友
1楼 · 发布于 2024-06-09 08:54:19

解决方案

bot模块的上下文中模拟Mastodon

范例

test_bot.py

import unittest
import bot
from unittest.mock import patch


class TestBot(unittest.TestCase):
    @patch("bot.Mastodon")
    def test_bot(self, mastodon_mock):
        b = bot.Bot()
        breakpoint()
        mastodon_mock.return_value = Mock()
        mastodon_mock.status_post.assert_called_with(
            b.reply_to_toot("1", account_name="@fake", message="test")
        )

机器人

import os
from mastodon import Mastodon

class Bot(object):
    #   Set up Mastodon
    def __init__(self, access_token="", base_address=""):
        self.mastadon = Mastodon(
            access_token,
            base_address
        )

    def reply_to_toot(post_id, account_name, message=None, status_notifications=None):
        media_ids = []
        for fn in os.listdir(str(settings.INPUT_FOLDER)):
            if fn.endswith(('.jpeg', '.png')):
                print(Path(fn))
                image_dict = self.mastodon.media_post(str(settings.INPUT_FOLDER / fn))
                media_ids.append(image_dict["id"])
        if message is not None:
            parts = []
            total_len = str(len(message) // settings.MAX_MESSAGE_LENGTH + 1)
            count = 1
            split_lines = message.splitlines(True)
            while split_lines:
                message_part = "@" + account_name + " {}/".format(count) + total_len + "\n\n"
                while split_lines != [] and len(message_part) + len(split_lines[0]) < settings.MAX_MESSAGE_LENGTH:
                    message_part += split_lines[0]
                    split_lines = split_lines[1:]
                parts.append(message_part)
                count += 1
            for part in parts:
                print(part)
                post_id = self.mastodon.status_post(status=part, media_ids=media_ids, in_reply_to_id=post_id)
        else:
            while media_ids:
                self.mastodon.status_post(status=message, media_ids=media_ids[0:4], in_reply_to_id=post_id)
                media_ids = media_ids[4:]

参考资料

部分模拟:https://docs.python.org/3/library/unittest.mock-examples.html#partial-mocking

相关问题 更多 >