用nock模拟soap服务

Mocking soap services with nock

本文关键字:服务 soap 模拟 nock      更新时间:2023-09-26

我正在研究一个与soap服务通信的node应用程序,使用foam模块将json解析为有效的soap请求,并在收到响应时再次返回。当与soap服务通信时,这一切都工作得很好。

我遇到的问题是为此编写单元测试(集成测试工作良好)。我使用nock来模拟http服务并发送回复。这个回复确实被foam解析,然后我可以对响应做出断言。

所以我不能传递json对象作为回复,因为foam期望soap响应。如果我尝试这样做,我会得到错误:

Error: Start tag expected, '<' not found

将XML存储在javascript变量中是痛苦的,并且不起作用(即在引号中包装它并转义内部引号是无效的),所以我想将模拟的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解析器不只是接受文件(这是有意义的)。流在测试之前是否没有完成?

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

我也在Github上提出了这个

遵循pgte的建议https://github.com/pgte/nock/issues/326我能够通过设置正确的标头,回复xml字符串(带转义引号)来实现此工作。

从pgte:

。我不太了解泡沫,但我猜你得把响应内容类型头(参见https://github.com/pgte/nock#specifying-reply-headers)所以客户端可以正确解析XML

下面是工作测试的样子:

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;
});