这是我要测试的功能:
def send_something():
conn = lib.conn.SSH1
conn.open()
conn.send('ls\n')
if 'home' not in conn.recbuf:
return lib.FAIL
conn.send('whoami\n')
if USER not in conn.recbuf:
return lib.FAIL
return lib.PASS
每次我调用conn.send()时,调用的输出都存储在conn.recbuf中。为了测试这一点,我需要每次调用conn.recbuf都要使其不同。 (我知道我可以将conn.recbuf更改为包含home和USER的字符串,但不适用于更复杂的功能)
这是到目前为止我在测试中提出的内容:
@mock.patch.object(demo_sequence.lib, 'conn')
def test_send_something(mock_conn):
mock_conn.SSH1.recbuf = 'home'
assert demo_sequence.lib.PASS == demo_sequence.send_something()
mock_conn.SSH1.send.assert_any_call('ls\n')
mock_conn.SSH1.send.assert_any_call('whoami\n')
显然,这失败了,因为conn.recbuf只是“ home”并且不包含USER。
我需要像conn.recbuf.side_effect = ['home',USER]之类的东西,但是仅在引用recbuf而不调用它时才可以工作。
答案 0 :(得分:1)
如果您可以将conn.recbuf更改为property,则可以使用PropertyMock获得所需的效果。
from unittest import mock
class Dummy:
def __init__(self, myattribute):
self._myattribute = myattribute
@property
def myattribute(self):
return self._myattribute
def test():
with mock.patch('__main__.Dummy.myattribute', new_callable=mock.PropertyMock) as mocked_attribute:
mocked_attribute.side_effect = [4,5,6]
d = Dummy("foo")
print(d.myattribute)
print(d.myattribute)
print(d.myattribute)
但是,对于您的实际问题,我认为对您的问题的评论似乎包含合理的方法。
答案 1 :(得分:0)
您要寻找的是side_effect
:https://docs.python.org/3/library/unittest.mock.html
假设mock
是您的模拟对象。然后,您可以执行以下操作:
mock.side_effect = [a,b,c]
然后,每次您调用mock
时,将返回列表中的下一个值。
mock() # -> a
mock() # -> b
mock() # -> c
答案 2 :(得分:0)
我早些时候在解决类似的问题,并找到了使用PropertyMock
的解决方案。就我而言,我想在测试用例中的其他位置存储一个值,以便在我要模拟的类上设置属性时通过side_effect
调用方法来断言。
我认为这也应该适合您的情况(如果我了解您要执行的操作)。
解决方案是将PropertyMock
用于属性recbuf
,并将side_effect
放在其中:
from unittest.mock import MagicMock, PropertyMock
conn = MagicMock()
type(conn).recbuf = PropertMock(side_effect=['home', USER])
只要访问属性recbuf
,就会调用副作用,在这种情况下,每次都会遍历['home', USER]
。我猜您也需要修补该USER
值,以免出现名称错误。
希望这行得通/有帮助!