gpt4 book ai didi

python - 我应该如何测试在循环中调用了多个函数?

转载 作者:行者123 更新时间:2023-11-28 21:19:40 25 4
gpt4 key购买 nike

如何确保所有处理程序都在循环中被调用?我想到的最好办法是模拟 fake_handler 函数并检查此函数是否被调用了一定次数,但我认为可能有更好的解决方案。

class MessageHandler:
def __init__(self, handlers=None):
self.handlers = handlers or []

def handle(self, event, body):
for handler in self.handlers:
handler(event, body)

测试:

def fake_handler(*args, **kwargs):
pass


class TestMessageHandler(TestCase):
@patch('tests.test_handlers.fake_handler')
def test_handle(self, fake_handler_mock):
messages = MessageHandler([fake_handler_mock, fake_handler_mock])
messages.handle(None, None)
self.assertEqual(fake_handler_mock.call_count, 2)

最佳答案

我在你的测试中看到了很多问题,总而言之你不应该打补丁而且你测试的太少了。让我一一解决。

不打补丁

真的,这是一个犯错或陷入其许多警告中的巨大机会。几乎每个教程都从使用补丁开始,以测试难以测试的代码。但是你的代码是可测试的,你不需要它,这也可以工作:

def test_handle(self):
handler = mock.Mock(name='handler')
messages = MessageHandler([handler, handler])
messages.handle(None, None)
self.assertEqual(handler.call_count, 2)

检查模拟调用中传递的参数

您的测试检查处理程序被调用了两次,但没有传递参数。您宁愿检查是否传递了正确的参数。

def test_handle(self):
handler = mock.Mock(name='handler')
messages = MessageHandler([handler, handler])
messages.handle(None, None)
self.assertEqual(
handler.mock_calls,
[mock.call(None, None), mock.call(None, None)]
)

实际检查参数

我们现在正在检查 None 是否已传递给处理程序,但事件和正文都是 None 并且其他任何内容都可能是 None所以我们真的不知道代码是否做出了正确的调用。最好为每个参数使用不同的唯一值。

def test_handle(self):
handler = mock.Mock(name='handler')
messages = MessageHandler([handler, handler])
messages.handle(mock.sentinel.event, mock.sentinel.body)
self.assertEqual(
handler.mock_calls,
[mock.call(mock.sentinel.event, mock.sentinel.body),
mock.call(mock.sentinel.event, mock.sentinel.body)]
)

使用不同的处理程序进行测试

两次使用相同的处理程序是一种极端情况。即使您可能想要保留此测试(或更改它;您真的想要允许重复的处理程序吗?),您确实想要测试处理程序不同的一般情况。

def test_handle(self):
handler1 = mock.Mock(name='handler1')
handler2 = mock.Mock(name='handler2')
messages = MessageHandler([handler1, handler2])
messages.handle(mock.sentinel.event, mock.sentinel.body)
handler1.assert_called_once_with(
mock.sentinel.event, mock.sentinel.body
)
handler2.assert_called_once_with(
mock.sentinel.event, mock.sentinel.body
)

检查处理程序是否按顺序调用

如果要断言调用是按顺序进行的,上面的测试是不够的。如果您更改断言的顺序,它仍然会通过。我知道检查调用不同模拟的顺序的唯一方法是使它们成为同一父模拟的属性。这根本不会让我开心,因为测试变得与我想要测试的行为无关的对象有关,但这似乎是唯一的方法。

def test_handle(self):
handlers_parent = mock.Mock(name='handlers_parent')
handler1 = handlers_parent.handler1
handler2 = handlers_parent.handler2
messages = MessageHandler([handler1, handler2])
messages.handle(mock.sentinel.event, mock.sentinel.body)
self.assertEqual(
handlers_parent.mock_calls,
[mock.call.handler1(mock.sentinel.event, mock.sentinel.body),
mock.call.handler2(mock.sentinel.event, mock.sentinel.body)]
)

关于python - 我应该如何测试在循环中调用了多个函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53294920/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com