使用Python unittest测试回调调用的正确方法是什么?

Lon*_*ner 2 python unit-testing callback python-3.x

我有一个类似于以下的应用程序代码.

# Filename: app.py
class Foo:
    def __init__(self):
        self.callback = None

    def set_handler(self, callback):
        self.callback = callback

    def run(self, details):
        name, age = details.split('/')
        if age.isdigit():
            age = int(age)
        else:
            age = -1
        return self.callback(name, age)
Run Code Online (Sandbox Code Playgroud)

如您所见,它提供了set_handler一种设置回调的方法.稍后必须使用两个参数调用回调:字符串和整数.我试图在单元测试中确保这一点.

# Filename: test_app.py
import unittest
from app import Foo

class AppTest(unittest.TestCase):
    def f(self, a, b):
        # This callback should get called with the first argument as
        # string and the second argument as integer
        return repr(a) + ',' + repr(b)

    def test_callback(self):
        foo = Foo()
        foo.set_handler(self.f)
        self.assertEqual(foo.run('John/20'), "'John',20")
        self.assertEqual(foo.run('John/xyz'), "'John',-1")

if __name__ == '__main__':
    unittest.main()
Run Code Online (Sandbox Code Playgroud)

该单元测试成功.但我不认为我的测试方式很强大.这个单元测试基本上是一个hack,因为我不知道如何正确测试是否使用正确类型的参数调用了回调.我觉得奇怪的是,AppTest的f方法是通过尝试返回由repr()参数组成的值来共享类型检查的责任,并且至少可以说这并不是完全可靠的.

请你帮助我好吗?是否有可能减轻f测试类型的责任方法?

tsr*_*ten 6

编辑:

尝试使用unittest.mock(Python 3.3上的标准库).它允许您断言如何调用方法.例如:

import unittest
from unittest.mock import Mock

from app import Foo

class AppTest(unittest.TestCase):

    def test_callback(self):
        foo = Foo()
        f = Mock()
        foo.set_handler(f)

        foo.run('John/20')
        f.assert_called_with('John', 20)

        foo.run('John/xyz')
        f.assert_called_with('John', -1)

if __name__ == '__main__':
    unittest.main()
Run Code Online (Sandbox Code Playgroud)