在Python中从WSDL文件创建模拟Web服务

15 投票
3 回答
10765 浏览
提问于 2025-04-15 18:26

我们正在为一个远程服务编写客户端,这个服务提供了SOAP网络服务,并且发布了这些服务的WSDL定义。

在测试期间,我们无法访问系统,所以我们想写一个模拟服务。我们使用Python来编写客户端,因此理想情况下,我们也希望用Python来创建模拟服务器,虽然我想这并不是绝对必要的。

我们的理想情况是能够从WSDL文件生成一些代码模板,然后我们可以填充这些模板,最后用Paste Deploy作为WSGI服务器来提供这些服务。不过,只要能可靠地工作,使用的服务器不一定非得是Paste Deploy或WSGI。最重要的是,我们需要从“真实”的WSDL文件生成这些代码模板,以免不小心写出一个不合规的模拟服务器。

我们在客户端使用suds这个库,并且也看过soaplib和ZSI。不过,soaplib里的wsgi2py部分在开头就说“不要使用”,而ZSI看起来又比较复杂。大家一般会用什么来处理这种情况呢?

马丁

3 个回答

3

你可以用这段代码来创建一个 suds 的模拟客户端。

from suds.client import Client

class AlwaysCallable(object):
    """
    Represents a chainable-access object and proxies calls to ClientMock.
    """

    name = None

    def __init__(self, client_cls):
        self._client_cls = client_cls

    def __call__(self, *args, **kwargs):
        try:
            hook = object.__getattribute__(self._client_cls, self.name)
        except AttributeError:
            pass
        else:
            return hook(self._client_cls, *args, **kwargs)

    def __getattr__(self, item):
        new = object.__getattribute__(self, '__class__')(self._client_cls)
        new.name = item
        return new


class ClientMock(Client):
    """
    Abstract mock suds client.
    """

    def __init__(self, url, **kwargs):
        pass

    def __getattr__(self, item):
        return AlwaysCallable(self.__class__)

    def __unicode__(self):
        return 'Client mock'

    def __str__(self):
        return 'Client mock'

接下来,定义一个具体的 ClientMock。

class UserCredentialsServiceClientMock(ClientMock):
    """
    Mock object that implements remote side services.
    """

    def GetUserInfo(cls, user_id):
        """
        Stub for remote service.
        """
        return UserInfo(id=user_id, name='Adam Smith')

现在你可以使用模拟库来伪造一段代码,这段代码使用了 suds.client.Client。

from unittest import TestCase
from mock import patch
from project.api import get_user_credentials

class UserCredentialsClientTestCase(TestCase):
    def test_getting_user_credentials(self):
        with patch('project.api.Client', new=UserCredentialsServiceClientMock):
            self.assertEquals(get_user_credentials(1), 'Adam Smith')
6

我建议你使用soapUI来创建一个模拟服务。这个工具安装起来非常简单,创建一个WS模拟服务也同样容易。它会从你指定的位置获取WSDL文件,然后根据这个文件的结构来生成请求的格式。如果你需要,它还可以根据WSDL文件的结构创建一个模拟的网络服务。

当你创建新的soapUI项目时,记得选择第三个复选框选项,这样就可以创建模拟的网络服务了。

如果需要xsd模式文件,确保它们在WSDL文件中有正确的引用。

虽然它不使用Python,但如果你只需要一个可以发送请求并获取响应的测试环境,那就足够了。

希望这些信息对你有帮助。

8

作为一个模拟服务器,我非常推荐使用soapUI(http://www.soapui.org)。

它可以读取一个WSDL文件,然后自动生成服务和服务方法。接下来,你可以定义静态的返回值,或者使用Groovy脚本来设置动态返回值。想了解更多,可以查看这里的文档,里面有关于网络服务模拟的详细说明。

soapUI有免费版和付费的专业版。我使用过免费版,效果非常好。

撰写回答