使用mock进行测试会引发异常



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

测试.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 + "nn"
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:Python35libunittestcase.py", line 58, in testPartExecutor
yield
File "C:Python35libunittestcase.py", line 600, in run
testMethod()
File "C:Python35libunittestmock.py", line 1157, in patched
return func(*args, **keywargs)
File "C:UsersHughPycharmProjectssummer-projecttesttest.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:UsersHughPycharmProjectssummer-projectsrcbot.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:UsersHughPycharmProjectssummer-projectvenvlibsite-packagesmastodonMastodon.py", line 102, in wrapper
return function(self, *args, **kwargs)
File "C:UsersHughPycharmProjectssummer-projectvenvlibsite-packagesmastodonMastodon.py", line 1776, in status_post
return self.__api_request('POST', '/api/v1/statuses', params, headers = headers, use_json = use_json)
File "C:UsersHughPycharmProjectssummer-projectvenvlibsite-packagesmastodonMastodon.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

解决方案

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")
)

bot.py

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 + "nn"
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-模拟

最新更新