使用PactV3测试GraphQL端点失败(PactV3 500内部服务器错误)



我试图用Pact JS在消费者端创建一个Pact。在PactJS v3中,.withQuery方法似乎被删除了,并且对GraphQL测试的通用支持不可用。很难使用上面提到的GraphQLInteraction交互,或者测试POST请求的纯主体,我想,但我不知道怎么做,因为一旦我向.requestWith方法添加主体,我就会得到错误:

Http failure response for http://... 500 Internal Server Error

问题是withRequest方法中的body属性。如果没有该属性,mock服务器不会抛出错误,但Pact当然不包括请求体,因此非常无用。

.withRequest({
method: 'POST',
path: `/product/graphql`,
headers: {
'Content-Type': 'application/json',
Accept: "application/json",
},
/*
* Adding a body to the request fails with:
* `Http failure response for http://127.0.0.1:4000/product/graphql: 500 Internal Server Error`
*
* The goal is to have the request body in the created Pact, because without it, it is
* quite useless.
*/
// body: requestBody,                                     // fails
// body: MatchersV3.like(requestBody),                    // fails
// body: MatchersV3.string(JSON.stringify(requestBody)),  // fails
})

我创建了一个GIT存储库,其中有一个尝试使用实体的最小示例。由于对因果报应的支持在Pact v10中被弃用,回购还包括切换到Jest

请求中似乎缺少operationName

日志提示:

[2022-08-13T11:48:06Z DEBUG pact_matching] --> Mismatches: [BodyMismatch { path: "$", expected: Some(b"["query","variables"]"), actual: Some(b"["operationName","query","variables"]"), mismatch: "Expected a Map with keys query, variables but received one with keys operationName, query, variables" }]
[2022-08-13T11:48:06Z DEBUG pact_mock_server::hyper_server] Request did not match: Request did not match - HTTP Request ( method: POST, path: /product/graphql, query: None, headers: Some({"Content-Type": ["application/json"], "Accept": ["application/json"]}), body: Present(68 bytes, application/json) )    0) $ -> Expected a Map with keys query, variables but received one with keys operationName, query, variables

作为正文发送的正确查询是:

const requestBody = { "operationName": "product", "query":"{ product { data { idProduct name } } }", "variables": null }

Pact JS中存在一个问题,因为测试本身正在失败,所以打印它对您没有帮助。PactJS的下一个版本应该会为您打印一个(更有用的(错误:

● Product Service › Given there are already some products in the database › should get a list of existing products
Test failed for the following reasons:
Mock server failed with the following mismatches:
0) The following request was incorrect:
POST /product/graphql
1.0 Expected a Map with keys query, variables but received one with keys operationName, query, variables

作为Matthew正确答案的实用补充:

Http failure response for http://... 500 Internal Server Error的解决方案

如前所述,这将在未来的《公约》版本中得到修正。只要你马上需要,你就可以从当前PR复制更改:

// /node_modules/@pact-foundation/pact/src/v3/pact.js
// replace the `executeTest` function with the following (tested with Pact v10.1.0 and v10.1.1)
// !! of course this will likely break the executeTest funtion in a later release when there are updates !!
PactV3.prototype.executeTest = function (testFn) {
return __awaiter(this, void 0, void 0, function () {
var scheme, host, port, server, val, e_1, matchingResults_1, error, matchingResults, success, error;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
scheme = this.opts.tls ? 'https' : 'http';
host = this.opts.host || '127.0.0.1';
port = this.pact.createMockServer(host, this.opts.port, this.opts.tls);
server = { port: port, url: "".concat(scheme, "://").concat(host, ":").concat(port), id: 'unknown' };
_a.label = 1;
case 1:
_a.trys.push([1, 3, , 4]);
return [4 /*yield*/, testFn(server)];
case 2:
val = _a.sent();
return [3 /*break*/, 4];
case 3:
e_1 = _a.sent();
matchingResults_1 = this.pact.mockServerMismatches(port);
error = 'Test failed for the following reasons:';
error += "nn  ".concat((0, display_1.generateMockServerError)(matchingResults_1, 't'));
this.cleanup(false, server);
throw new Error((error += "nn Original exception: n".concat(e_1)));
case 4:
matchingResults = this.pact.mockServerMismatches(port);
success = this.pact.mockServerMatchedSuccessfully(port);
// Feature flag: allow missing requests on the mock service
if (!success && (0, display_1.filterMissingFeatureFlag)(matchingResults).length > 0) {
error = 'Test failed for the following reasons:';
error += "nn  ".concat((0, display_1.generateMockServerError)(matchingResults, 't'));
this.cleanup(false, server);
return [2 /*return*/, Promise.reject(new Error(error))];
}
this.cleanup(true, server);
return [2 /*return*/, val];
}
});
});
};

最新更新