python - python模拟不同的实例
问题描述
我想知道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())正在调用该函数。
现在,如何设置执行方法的 return_value?
例如:- 我需要模拟我的执行方法的响应。
所以,它应该是 pg.connect().cursor().execute.side_effect = someexception()
解决方案
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__
and__call__
和__eq__
dunder 方法。虽然对象具有提供属性的正常方式,__getattribute__
但如果请求属性,则让类做任何它想做的事情。
当您将其称为Mock(spec=psycopg2)
时,它将做两件与 不同的主要事情Mock()
:
- 它调整其
__class__
字段以声称是psycopg2
。 - 检查 psycopg2 的有效属性,
AttributeError
如果您尝试获取不存在的字段,请提出。
但除此之外,它仍然表现得像一个普通的模拟。如果您调用yourMock.foo
,它不知道它是属性还是方法。它只是返回一个新Mock
实例,并且因为该实例是可调用的,所以您可以像调用函数一样调用它。
更新:如果你设置 spec on Mock
,它会限制可用的属性。要添加规范未提供的属性,您只需要在初始化时设置它:
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的方法。
推荐阅读
- r - 如何从 download.file 请求中捕获 HTTP 错误代码?
- arduino - 如何让 Arduino IDE 自动上传文件?
- html - HTML 如何让它在您的网站上显示 čšž
- angular - 让一个类评估一个在 Angular 应用程序中不起作用的表达式
- apache-spark - 从 pyspark.sql.dataframe.DataFrame 到 arraytype
- python - OpenCV 霍夫线
- javascript - addEventListener 与媒体冲突
- c++ - 如果打开了堆栈保护器,为什么clang会生成rsqrt?
- java - Gitlab 上 GCP App Engine 的 Maven 部署
- python - 从另一个嵌套类访问属性