我有一个方法,它需要包含某些条目的dict作为参数。例如,我可能期望dict中的type
键的值必须是['typeA', 'typeB', 'typeC']
之一。如果缺少某个键,我会使用该方法抛出异常SpecFormatException
。异常消息应为'type' entry is missing in spec dict: {'foo': 'bar', 'baz': [1, 2, 3]}
。
我正在编写一个测试来验证是否正在使用正确的错误消息抛出异常,但由于dict.__str__()
方法的输出是不确定的,因此我的测试很不稳定。我想如果我可以修补dict.__str__()
方法输出类似"是的我就是你的字典"然后我可以修复片状,但是当我尝试用以下方法修补我的测试时:
import mock
import my_verifier
@mock.patch('my_verifier.dict')
def testErrorMessage(this, dict_str):
dict_str.return_value = 'YES I AM YOUR DICTIONARY'
...
我收到错误消息" my_verifier.py没有属性' dict'"在试图进行测试时。
我假设嘲笑__str__
方法是正确的方法,但我该如何做呢?
答案 0 :(得分:1)
您对错误消息的测试需要具体吗?您是否可以断言您期望的部分内容,例如:
def function():
global x
x = x + 1
if x <= 5: print(x)
显然,您可能还需要测试邮件的其他部分。对EXACT字符串的测试可能或不是您想要做的,因为该消息可能会更改。如果您需要沿着这条路走下去,我建议将字符串(或字符串模板)存储在可以被所有内容访问的地方,这样您的测试就可以根据类变量或配置参数进行断言。
答案 1 :(得分:0)
如果使用自定义dict2str函数替换内置dict.__str__
方法是一个选项,则可以按字母顺序对键进行排序:
def det_str(x):
if isinstance(x, dict):
return '{{{}}}'.format(', '.join('{!r}: {}'.format(k, det_str(v)) for k, v in sorted(x.items())))
else:
return str(x)
>>> det_str({'a': 1, 'b': 0, 'c': -1})
"{'a': 1, 'b': 0, 'c': -1}"
>>> det_str({'c': -1, 'a': 1, 'b': 0})
"{'a': 1, 'b': 0, 'c': -1}"
也递归地工作:
>>> det_str({'b': 0, 'a': 1, 'c': -1, 'd': {'z': 10, 'x': 20, 'y': -30}})
"{'a': 1, 'b': 0, 'c': -1, 'd': {'x': 20, 'y': -30, 'z': 10}}"
答案 2 :(得分:0)
我会假设你在引发异常时将字典作为参数传递,例如
d = {'foo': 'bar', 'baz': [1, 2, 3]}
if not d.get('type') in ['typeA', 'typeB', 'typeC']:
raise SpecFormatException(d)
第一个测试将仅关注异常本身,这意味着参数并不重要,只要它具有__str__
方法:
def testExceptionMessage(self):
d = mock.MagicMock()
exc = SpecFormatException(d)
observed = str(exc)
self.assertEqual(observed,
"'type' entry is missing in spec dict: {}".format(d)
如果您在调用d.__str__.called
之前和之后检查str(exc)
的值,您会看到值从False
更改为True
,验证SpecFormatException
确实使用参数的__str__
方法来创建observed
的值。
第二个测试侧重于按预期引发的异常。你真的不需要检查它的消息是什么,因为1)你已经在其他地方测试过了,2)消息实际上并不包含你无法从dict
实例本身收集的任何信息事实上SpecFormatException
确实被提出了。
def testRaiseException(self):
with self.assertRaises(SpecFormatException):
# code that should cause SpecFormatException be raised
答案 3 :(得分:0)
这是一个较旧的问题,但我遇到了同样的困难,无法找到有效的答案。我最终使用unittest.mock.MagicMock
模拟对象函数的__str__
输出。 MagicMock
是designed来模拟Python的魔术功能,例如__str__
。
对于测试本身,您不需要使用诸如SpecFormatException
之类的东西。您可以使用mock.patch
作为上下文管理器-您的代码如下所示:
import my_verifier
import unittest.mock
def test_my_method_error_message():
with mock.patch("my_verifier.dict", mock.MagicMock()) as mock_dict:
mock_dict.__str__.return_value = "YES I AM YOUR DICTIONARY"
assert str(mock_dict) == "YES I AM YOUR DICTIONARY"
# ...other tests that rely on a mocked instance of my_verifier.dict...
# ...other tests that don't rely on a mocked instance of my_verifier.dict...
假设my_verifier
有一个dict
对象/方法,这使您可以控制一个或多个测试的打印my_verifier.dict
的输出,而不必完全替换my_verifier.dict
一个模拟对象。
您还可以在同一上下文中模拟my_verifier.dict
的其他(魔术)函数,并使任何其他测试驻留在上下文之外。
patch.object方法也可能有用。