简体   繁体   English

有人有使用 Python Zeep 和 Mock 对 SOAP API 进行单元测试的示例吗?

[英]Does someone have an example of Unit-Testing a SOAP API with Python Zeep and Mock?

I'm building a Python app that accesses a 3rd party SOAP API with Python-zeep.我正在构建一个使用 Python-zeep 访问第 3 方 SOAP API 的 Python 应用程序。 I want to implement some unit-tests using mocked responses as I don't always have a live server to run my tests against.我想使用模拟响应来实现一些单元测试,因为我并不总是有一个实时服务器来运行我的测试。

I'm new to unit-testing and not quite sure where to start.我是单元测试的新手,不太确定从哪里开始。 I've seen examples of using mock with the requests library, but not really sure how to translate this into Zeep.我已经看到了将 mock 与 requests 库一起使用的示例,但不确定如何将其转换为 Zeep。

On one of my Models I have a method to get all DevicePools from a SOAP API.在我的一个模型上,我有一种从 SOAP API 获取所有 DevicePools 的方法。 Here's an excerpt of the relevant code (I use a helper method to provide the service object as I plan on using this in many other methods).这是相关代码的摘录(我使用辅助方法来提供服务对象,因为我计划在许多其他方法中使用它)。

# Get Zeep Service Object to make AXL API calls
service = get_axl_client(self)

# Get list of all DevicePools present in the cluster
resp = service.listDevicePool(searchCriteria={'name': '%'},
                              returnedTags={'name': '', 'uuid': ''})

I want to mock the resp object, however this is of type zeep.objects.ListDevicePoolRes (a dynamic type based on the parsing of the WSDL) and I can't just instantiate an object with static values.我想模拟 resp 对象,但是这是 zeep.objects.ListDevicePoolRes 类型(基于 WSDL 解析的动态类型),我不能只用静态值实例化一个对象。

Maybe I'm on the wrong track here and would have to go a bit deeper and actually mock some internals of the zeep library and replace the requests response before zeep parses the XML?也许我在这里走错了路,必须更深入地实际模拟 zeep 库的一些内部结构,并在 zeep 解析 XML 之前替换请求响应?

If someone had an example of something similar it would be greatly appreciated.如果有人有类似的例子,将不胜感激。

After looking through the Python Zeep source code, I found some examples of tests using the requests-mock library which I was able to work into my solution.在查看了 Python Zeep 源代码后,我发现了一些使用 requests-mock 库的测试示例,我可以将它们用于我的解决方案。 Here's a working example in case anyone else is trying to do something similar.这是一个工作示例,以防其他人尝试做类似的事情。

I'm not doing any assertions in this example as I first wanted to prove the concept that I could get zeep to parse a mock response correctly.在这个例子中我没有做任何断言,因为我首先想证明我可以让 zeep 正确解析模拟响应的概念。

# -*- coding: utf-8 -*-

from zeep import Client
from zeep.cache import SqliteCache
from zeep.transports import Transport
from zeep.exceptions import Fault
from zeep.plugins import HistoryPlugin
from requests import Session
from requests.auth import HTTPBasicAuth
from urllib3 import disable_warnings
from urllib3.exceptions import InsecureRequestWarning
from lxml import etree
import requests_mock

disable_warnings(InsecureRequestWarning)

username = 'administrator'
password = 'password'
host = 'cucm-pub'

wsdl = 'file://C:/path/to/axlsqltoolkit/schema/current/AXLAPI.wsdl'
location = 'https://{host}:8443/axl/'.format(host=host)
binding = "{http://www.cisco.com/AXLAPIService/}AXLAPIBinding"

session = Session()
session.verify = False
session.auth = HTTPBasicAuth(username, password)

transport = Transport(cache=SqliteCache(), session=session, timeout=20)
history = HistoryPlugin()
client = Client(wsdl=wsdl, transport=transport, plugins=[history])
service = client.create_service(binding, location)

def test_listPhone():
    text = """<?xml version="1.0" ?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
  <soapenv:Body>
    <ns:listDevicePoolResponse xmlns:ns="http://www.cisco.com/AXL/API/11.5">
      <return>
        <devicePool uuid="{1B1B9EB6-7803-11D3-BDF0-00108302EAD1}">
          <name>AU_PER_DP</name>
        </devicePool>
        <devicePool uuid="{BEF5605B-1DB0-4157-0176-6C07814C47AE}">
          <name>DE_BLN_DP</name>
        </devicePool>
        <devicePool uuid="{B4C65CAB-86CB-30FB-91BE-6F6E712CACB9}">
          <name>US_NYC_DP</name>
        </devicePool>
      </return>
    </ns:listDevicePoolResponse>
  </soapenv:Body>
</soapenv:Envelope>
    """


    with requests_mock.Mocker() as m:
        m.post(location, text=text)
        resp = service.listDevicePool(searchCriteria={'name': '%'},
                                      returnedTags={'name': '',
                                                    'uuid': ''})

    return resp

test_listPhone()

This then gives me the following result (have manually removed all the attributes with "none" that Zeep includes for brevity):然后,这给了我以下结果(为简洁起见,已手动删除了 Zeep 包含的所有“无”属性):

{
    'return': {
        'devicePool': [
            {
                'name': 'AU_PER_DP',
                'uuid': '{1B1B9EB6-7803-11D3-BDF0-00108302EAD1}'
            },
            {
                'name': 'DE_BLN_DP',
                'uuid': '{BEF5605B-1DB0-4157-0176-6C07814C47AE}'
            },
            {
                'name': 'US_NYC_DP',
                'uuid': '{B4C65CAB-86CB-30FB-91BE-6F6E712CACB9}'
            }
        ]
    },
    'sequence': None
}

I had the same need today and did a little research and started in zeeps test cases.我今天也有同样的需求,做了一些研究并开始使用 zeeps 测试用例。 The link ( https://github.com/mvantellingen/python-zeep/blob/2f35b7d29355ba646f5e3c6e9925033d5d6df8bb/tests/test_client.py#L109 ) points to an excample that shows how easy it is to test that by mocking the GET/POST by defining the data returned by them.该链接( https://github.com/mvantellingen/python-zeep/blob/2f35b7d29355ba646f5e3c6e9925033d5d6df8bb/tests/test_client.py#L109 )指向一个示例,该示例显示了通过定义模拟 GET/POST 来测试它是多么容易他们返回的数据。

This returned data then makes its way through zeep and ends with the same result as it would come from the remote source.然后返回的数据通过 zeep 并以与来自远程源的相同结果结束。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM