用诺克模拟肥皂服务

Mocking soap services with nock

我正在开发一个与 soap 服务通信的 node 应用程序,使用 foam 模块将 json 解析为有效的 soap 请求,并在响应为已收到。在与 soap 服务通信时,一切正常。

我遇到的问题是为此编写单元测试(集成测试工作正常)。我正在使用 nock 模拟 http 服务并发送回复。 foam 确实解析了此回复,然后我可以针对该回复做出断言。

所以我无法将 json 对象作为回复传递,因为 foam 需要 soap 回复。如果我尝试这样做,我会收到错误消息:

Error: Start tag expected, '<' not found

在 javascript 变量中存储 XML 是痛苦的并且不起作用(即用引号将其包装并转义内部引号无效),所以我想把模拟的 XML 将响应写入文件并将其作为答复传递。

我试过以流的形式读取文件

return fs.createReadStream('response.xml')

...并用文件回复

.replyWithFile(201, __dirname + 'response.xml');

两者均失败,错误为

TypeError: Cannot read property 'ObjectReference' of undefined

这里是文件中的XML

<env:Envelope xmlns:env='http://schemas.xmlsoap.org/soap/envelope/'>
    <env:Header></env:Header>
    <env:Body>
        <FLNewIndividualID xmlns='http://www.lagan.com/wsdl/FLTypes'>
            <ObjectType>1</ObjectType>
            <ObjectReference>12345678</ObjectReference>
            <ObjectReference xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xsi:nil='true'/>
            <ObjectReference xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xsi:nil='true'/>
        </FLNewIndividualID>
    </env:Body>
</env:Envelope>

正在测试的模块是

var foam = require('./foam-promise.js');

module.exports = {
    createUserRequest: function(url, operation, action, message, namespace) {
        var actionOp = action + '/actionRequestOp',
            uri = url + '/actionRequest';

        return new Promise(function(resolve, reject) {
            foam.soapRequest(uri, operation, actionOp, message, namespace) 
            .then(function(response) {
                resolve(response.FLNewIndividualID.ObjectReference[0]);
            })
            .catch(function(err) {
                reject(err);
            });
        });

    }
};

断言正在使用 should-promised

return myRequest(url, operation, action, data, namespace)
    .should.finally.be.exactly('12345678');

所以看起来 xml 解析器不会只接受一个文件(这是有道理的)。流在测试之前是否未完成?

XML 回复可以用 nock 成功模拟吗?

我也在 Github

上提出了这个问题

在这里遵循 pgte 的建议 https://github.com/pgte/nock/issues/326 我能够通过设置正确的 headers 来实现它,用 xml 字符串(带转义引号)回复。

来自 pgte:

It can. I don't know foam well, but I guess you have to set the response content type header (see https://github.com/pgte/nock#specifying-reply-headers ) so that the client can parse the XML correctly.

这是工作测试的样子:

it('should return a user ID', function(){
    var response = '<env:Envelope xmlns:env=\'http://schemas.xmlsoap.org/soap/envelope/\'><env:Header></env:Header><env:Body><UserReference>12345678</UserReference></env:Body></env:Envelope>'

    nock(url)
        .post('/createUserRequest')
        .reply(201, response, {
                'Content-Type': 'application/xml'
              }
        );

    return createUserRequest(url, operation, action, message, options)
        .should.be.fulfilledWith('12345678');
});

it('should be rejected if the request fails', function() {

    nock(url)
        .post('/createCaseRequest')
        .replyWithError('The request failed');

    return createUserRequest(url, operation, action, message, options)
        .should.be.rejected;
});