我有一个使用 elasticsearch 的类,我正在尝试为它编写单元测试。
from elasticsearch import Elasticsearch
class MyClass:
def __init__(self):
# ...
self.client = Elasticsearch(connection) # Connect to ES
def get_mapping(self):
mapping = self.client.indices.get_mapping(
index=self.index_name
)
# ... extra code that simplifies mapping
return mapping
这是我在单元测试中的内容:
from myproject.module.submodule import MyClass
class MyTestCase(unittest.TestCase): # pragma: no cover, duplicates expected
def setUp(self):
patcher = mock.patch('elasticsearch.Elasticsearch')
self.mock_es = patcher.start()
self.addCleanup(patcher.stop)
def test_mapping(self):
self.mock_es.indices.get_mapping.return_value = {
"some_index": {
"mappings": {
"properties": {
"field_one": {
"type": "text",
},
"field_two": {
"type": "text",
}
}
}
}
}
mapping = MyClass().get_mapping()
expected_mapping = {
"some_index": {
"field_one": "text",
"field_two": "text",
}
}
self.assertEqual(mapping, expected_mapping)
我的期望是,在运行单元测试时,实际 elasticsearch
库不应该被使用。
但是,当我运行上面的代码时,它会尝试连接到 elasticsearch。
我做错了什么?
答案 0 :(得分:0)
我想通了。需要进行两项更改:
在 setUp() 中,我需要修补 elasticsearch.Elasticsearch
而不是修补 myproject.module.submodule.Elasticsearch
。
评论中提到了这一点。
代替 self.mock_es.indices.get_mapping.return_value = <some_value>
应该是:
instance = self.mock_es.return_value
instance.indices.get_mapping.return_value = <some_value>
在模拟一个类之后,为了能够模拟一个方法的返回值,需要模拟每个实例,而不是类方法。
所以最后的测试类是:
class MyTestCase(unittest.TestCase): # pragma: no cover, duplicates expected
def setUp(self):
patcher = mock.patch('myproject.module.submodule.Elasticsearch')
self.mock_es = patcher.start()
self.addCleanup(patcher.stop)
def test_mapping(self):
instance = self.mock_es.return_value
instance.indices.get_mapping.return_value = {
"some_index": {
"mappings": {
"properties": {
"field_one": {
"type": "text",
},
"field_two": {
"type": "text",
}
}
}
}
}
mapping = MyClass().get_mapping()
expected_mapping = {
"some_index": {
"field_one": "text",
"field_two": "text",
}
}
self.assertEqual(mapping, expected_mapping)