TypeError: object is not callable when instantiating during unit test

TypeError: object is not callable when instantiating during unit test

我有一个 class 在用错误的值实例化时抛出异常,我想编写一个单元测试在给定错误参数时抛出异常。

在 self.assertRaises() 之外实例化一个对象似乎不会导致任何错误,我不明白为什么当我尝试在 assert

中实例化它时它会导致错误

我的 class 看起来像这样:

class Mark:
    def __init__(self, a, b, c):
        try:
            self.a = a
            self.b = int(b)
            self.c = int(c)
        except ValueError:
            print(e)

我的测试是这样的:

import unittest
import main


class Test(unittest.TestCase):

    def test_marks(self):

        self.assertRaises(ValueError, main.Mark("X", 5, 32))
        self.assertRaises(ValueError, main.Mark(1, "X", 32))
        self.assertRaises(ValueError, main.Mark(1, 5, "X"))


if __name__ == "__main__":
    unittest.main()

但我得到:

(base) ➜  Code Python3 test.py
E
======================================================================
ERROR: test_marks (__main__.Test)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/Code/test.py", line 12, in test_marks
    self.assertRaises(ValueError, main.Mark("X", 5, 32))
  File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/unittest/case.py", line 733, in assertRaises
    return context.handle('assertRaises', args, kwargs)
  File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/unittest/case.py", line 201, in handle
    callable_obj(*args, **kwargs)
TypeError: 'Mark' object is not callable

----------------------------------------------------------------------
Ran 1 test in 0.001s

FAILED (errors=1)

你知道如果我想测试这个应该怎么做吗?

assertRaises() 期望 callable 而不是 called 函数。

您只需提供可调用对象并在没有 () 的情况下附加参数:

self.assertRaises(ValueError, main.Mark, "X", 5, 32)

或者,您可以使用上下文管理器:

with self.assertRaises(ValueError):
    main.Mark("X", 5, 32)

assertRaises 的签名与您的用法不同。参见 documentation Here

您应该为它提供一个可调用对象和调用它时应使用的参数,或者您应该使用 with 语句并照常调用它。

这是一个片段,显示了两种方法:

def test_marks(self):
    self.assertRaises(ValueError, main.Mark, "X", 5, 32)
    with self.assertRaises(ValueError):
        main.Mark(1, "X", 32)

根据您修改后的问题: 你实际上并没有抛出异常,而是在你的代码中捕获了它,所以断言失败了,因为你没有做你期望的事情。测试成功!

现在,如果你想检查异常是否按预期被捕获,你应该测试是否打印了 print 语句:

import contextlib
import io
import unittest

import main

class Test(unittest.TestCase):

    def test_marks(self):
        with contextlib.redirect_stdout(io.StringIO()) as f:
            main.Mark(1, 2, 3)
            output = f.getvalue().strip()
            assert output == 'I am an exception'


if __name__ == "__main__":
    unittest.main()

我们在这里做的是将标准输出重定向到一个简单的文本流,然后调用您的方法,捕获输出(剥离它以删除任何未知的空格)并检查输出的字符串是否与我们预期的相同它是。 在我的例子中,我只打印 "I am an exception"。您应该将其替换为异常的输出。