在 Robot Framework 中使用 SUDS 库和 MessagePlugin 创建带有 objectTypes 的 Soap 消息

Creating Soap messages with objectTypes using SUDS library and MessagePlugin in Robot Framework

这是这个问题的延续:Creating Soap messages with objectTypes using SUDS library in Robot Framework

在那里确定使用 RF SUDS 无法单独使用 SUDS 创建具有对象类型的消息。我想尝试 MessagePlugin 方法,但不幸的是文档中的信息对我来说还不够:

from robot.libraries.BuiltIn import BuiltIn
from suds.plugin import MessagePlugin

class _MyPlugin(MessagePlugin):
    def marshalled(self, context):
        body = context.envelope.getChild('Body')
        foo = body[0]
        foo.set('id', '12345')
        foo.set('version', '2.0')

class SudsLibraryExtensions(object):
    def attach_my_plugin(self):
        client = BuiltIn().get_library_instance("SudsLibrary")._client()
        # prepend so SudsLibrary's plugin is left in place
        plugins = client.options.plugins
        if any(isinstance(x, _MyPlugin) for x in plugins):
            return
        plugins.insert(0, _MyPlugin())
        client.set_options(plugins=plugins)

有人有关于如何使用上述代码段的完整机器人示例吗?我应该将什么作为上下文传递给编组?我需要在某个时候调用 attach_my_plugin() 吗?

消息插件的一般描述可以在 Suds documentation. More detail is in the class documentation. You do not call marshalled, suds does. To better understand how to implement the marshalled method, read up on the documentation for Element 中找到。 suds 插件本质上是一个监听器。我的示例使用 public Web 服务进行演示。

说你的请求是这样的:

...
<ns0:Body>
    <ns1:GetStatistics>
      <ns1:X>
...

但你需要它看起来像这样:

....
<ns0:Body>
    <ns1:GetStatistics type="specialType">
      <ns1:X>
 ...

这是一个将类型属性添加到 GetStatistics 元素的插件。当一个元素有子元素和属性被发送时,这可能是必要的。 Suds 0.4 不支持这一点,但它是有效的 SOAP。可能有一个支持此功能的 Suds 叉子。

*** Settings ***
Library           SudsLibrary
Library           c:/SudsLibraryExtensions.py

*** Test Cases ***
Message Plugin
    Create Soap Client    http://www.webservicex.net/Statistics.asmx?WSDL
    Attach My Plugin
    Set GetStats Type    specialType
    ${dbl array}=    Create Wsdl Object    ArrayOfDouble
    Append To List    ${dbl array.double}    2.0
    Append To List    ${dbl array.double}    3.0
    ${result}=    Call Soap Method    GetStatistics    ${dbl array}
    Should Be Equal As Numbers    ${result.Average}    2.5

c:/SudsLibraryExtensions.py 的内容:

from robot.libraries.BuiltIn import BuiltIn
from suds.plugin import MessagePlugin

class _MyPlugin(MessagePlugin):

    def __init__(self):
        self._type = 'defaultType'

    def marshalled(self, context):
        body = context.envelope.getChild('Body')
        call = body.getChild('GetStatistics')
        call.set('type', self._type)

    def set_getstats_type(self, value):
        self._type = value

class SudsLibraryExtensions(object):
    def attach_my_plugin(self):
        client = BuiltIn().get_library_instance("SudsLibrary")._client()
        plugins = client.options.plugins
        if any(isinstance(x, _MyPlugin) for x in plugins):
            return
        # prepend so SudsLibrary's plugin is left in place
        plugins.insert(0, _MyPlugin())
        client.set_options(plugins=plugins)

    def set_getstats_type(self, value):
        self._get_plugin().set_getstats_type(value)

    def _get_plugin(self):
        client = BuiltIn().get_library_instance("SudsLibrary")._client()
        plugins = client.options.plugins
        my_plugin = next((plugin for plugin in plugins if isinstance(plugin, _MyPlugin)), None)
        if my_plugin is None:
            raise RuntimeError("Plugin not found. Did you call Attach My Plugin?")
        return my_plugin

只要使用关键字 Attach My Plugin 附加插件,就会始终设置 type 属性。有一个默认类型。要更改类型的值,使用关键字 Set GetStats Type。任何类型集都将在所有未来的请求中使用,直到它被更改。这里使用两个类的唯一原因是为了防止"marshalled"成为暴露的关键字。