我想知道pg.connect
和pg.connect()
陈述之间的区别。
pg
是一个psycopg2模拟对象,当我显示dir
时,它会显示connect作为其方法。
class TestMock(unittest.TestCase):
def setUp(self):
pass
def test_mock_calls(self):
import pprint
pg = mock.MagicMock(psycopg2)
print 'pg() object ', pg()
print 'dir of pg = ', pprint.pprint(dir(pg))
print 'dir of pg = ', pg.connect
print 'dir of pg.connect = ', pprint.pprint(dir(pg.connect))
print 'dir of pg = ', pg.connect()
print 'dir of pg.connect() = ',
pprint.pprint(dir(pg.connect()))
更新: - 一个(pg.connect)正在访问该属性,另一个(pg.connect())正在调用该函数。
现在,我如何设置execute方法的return_value?
例如: - 我需要模拟执行方法的响应。
所以,它应该是pg.connect()。cursor()。execute.side_effect = someexception()
答案 0 :(得分:0)
Python非常注重文字。表达式pg.connect()
转换为:
pg
connect
。因此表达式pg.connect
将获取该方法,但不会调用它。事实上,您可以将该方法用作常规值并传递给它,因此my_connect = pg.connect
完全有效,稍后您可以调用my_connect()
。
我们可以看到dis
模块发生了什么:
import dis
dis.dis(lambda: pg.connect())
1 0 LOAD_GLOBAL 0 (pg)
2 LOAD_ATTR 1 (connect)
4 CALL_FUNCTION 0
6 RETURN_VALUE
由于Mock
想要伪装成不同的对象,因此它会覆盖标准的__getattribute__
和__call__
以及__eq__
dunder方法。虽然对象具有提供属性的常规方式,但__getattribute__
允许类在请求属性时执行任何操作。
当您将其称为Mock(spec=psycopg2)
时,它将以与Mock()
不同的方式执行两项主要操作:
__class__
字段以声明为psycopg2
。AttributeError
。但除此之外,它仍然表现为常规模拟。如果您致电yourMock.foo
,则不知道它是属性还是方法。它只返回一个新的Mock
实例,因为该实例是可调用的,所以你可以像函数一样调用它。
更新:如果您在Mock
上设置了规范,则会限制可用的属性。要添加spec未提供的属性,只需在初始时设置它:
cursor_mock = Mock(side_effect=psycopg2.DatabaseError)
Mock(spec=psycopg2.connect, cursor=cursor_mock)
您还需要此行为:pg.connect().cursor().execute.side_effect = someexception()
。通常,您需要更改return_value
:
cursor_mock = Mock()
cursor_mock.return_value.execute.side_effect = SomeException
# Same as:
cursor_mock = Mock(return_value=Mock(execute=Mock(side_effect=SomeException)))
您也可以执行cursor_mock().execute.side_effect = SomeException
,但这会污染cursor_mock.mock_calls
。
小点:我使用Mock
表示简洁,MagicMock
是相同的,只需添加一些dunder方法。