python - 使用模拟测试引发异常
问题描述
我有一个奇怪的错误,我无法理解。我正在尝试测试一个方法是否在另一个方法中被调用。我在 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 + "\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
解决方案
解决方案
在模块Mastodon
的上下文中模拟bot
例子
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
推荐阅读
- python - subprocess.check_output 与 sed - 得到不正确的结果 - 返回返回 \x01\n
- scrapy - 为什么scrapy爬取引号会导致GET错误?
- pandas - pandas 将所有字符串转换为数字(一种热编码)以进行回归
- google-sheets - 如何根据特定标准反映多个单元格
- c - 延迟初始化具有多线程读取器的数组:没有障碍或原子是否安全?
- python - 如何根据对话框中的事件在主窗口中填充列表
- android - 请求位置更新从未调用 onLocationResult
- python - Keras 自定义层(将另一个自定义层作为超类)不接受多个输入
- c - 如何将此功能代码减少到最多 25 行?
- c# - LogManager.GetLogger("Name") 和 LogManager.GetCurrentClassLogger() 有什么区别?