Error with Typescript Pact.io test: PopsicleError: Unable to connect to
Error with Typescript Pact.io test: PopsicleError: Unable to connect to
预期: 运行 npm run pactTest
应生成协议文件 (JSON).
结果: 我收到 Unable to connect
错误。
Pact.io JavaScript implementation guide.
Pact.io Typescript test example.
感谢任何关于我做错的想法或想法:)
错误
FAIL src/services/api/TotalPayout.test.pact.ts
The API
getUsersTotalPayout
✕ Should call getUsersTotalPayout and return an object with the total_payout (45ms)
● The API › getUsersTotalPayout › Should call getUsersTotalPayout and return an object with the total_payout
PopsicleError: Unable to connect to "http://127.0.0.1:12345/interactions"
Caused by: Error: connect ECONNREFUSED 127.0.0.1:12345
at Request.Object.<anonymous>.Request.error (node_modules/popsicle/src/request.ts:91:12)
at ClientRequest.<anonymous> (node_modules/popsicle/src/index.ts:218:31)
package.json 脚本:
"pactTest": "export NODE_ENV=pactTest && jest --testRegex \"/*(.test.pact.ts)\" --runInBand --setupFiles ./pactSetup.ts --setupTestFrameworkScriptFile ./pactTestWrapper.ts",
我的src/pactSetup.ts文件
// @ts-ignore
import path from 'path';
import { Pact } from '@pact-foundation/pact/pact';
// @ts-ignore
global.provider = new Pact({
port: 1234,
log: path.resolve(process.cwd(), 'logs', 'mockserver-integration.log'),
dir: path.resolve(process.cwd(), 'pacts'),
spec: 2,
cors: true,
pactfileWriteMode: 'update',
consumer: 'Exchange',
provider: 'LP Service'
});
我的src/pactTestWrapper.ts
jasmine.DEFAULT_TIMEOUT_INTERVAL = 10000; // This is to give the pact mock server time to start
// @ts-ignore
beforeAll(() => provider.setup()); // Create mock provider
// @ts-ignore
afterEach(() => provider.verify()); // Ensure the mock provider verifies expected interactions for each test
// @ts-ignore
afterAll(() => provider.finalize()); // Tear down the mock and write the pact
测试:src/services/api/TotalPayout.test.pact.ts
// @ts-ignore
import path from 'path';
import { Pact } from '@pact-foundation/pact';
import { getTotalPayout } from './apiPayout';
const port = 12345;
const endpoint = '/frontoffice/api/get-total-payout';
const EXPECTED_BODY = {
total_payout: 100.21,
};
const userId = 'foo';
const provider = new Pact({
port,
log: path.resolve(process.cwd(), 'logs', 'mockserver-integration.log'),
dir: path.resolve(process.cwd(), 'pacts'),
spec: 2,
consumer: 'Exchange',
provider: 'LP Service',
pactfileWriteMode: 'merge'
});
describe('The API', () => {
// Copy this block once per interaction under test
describe('getUsersTotalPayout', () => {
beforeEach(() => {
const interaction = {
uponReceiving: 'a GET request with a user id',
withRequest: {
method: 'GET',
path: endpoint,
headers: {
Accept: 'application/json',
},
},
willRespondWith: {
status: 200,
headers: {
'Content-Type': 'application/json'
},
body: EXPECTED_BODY
},
};
// @ts-ignore
return provider.addInteraction(interaction);
});
// add expectations
it('Should call getUsersTotalPayout and return an object with the total_payout', done => {
getTotalPayout(userId)
.then((response: any) => {
expect(response).toEqual(EXPECTED_BODY);
})
.then(done);
});
});
});
api服务文件apiPayout.ts
// @ts-ignore
import axios, * as others from 'axios';
const endpoint = '/frontoffice/api/';
export const getTotalPayout = async (userId: string) => {
const response = await axios.get(`${endpoint}get-total-payout`, { params: userId });
return response.data;
};
来自模拟服务器-integration.log
I, [2018-09-19T11:07:41.259437 #79922] INFO -- : Verifying - interactions matched
I, [2018-09-19T11:07:41.264440 #79922] INFO -- : Cleared interactions
来自调试日志
20 error code ELIFECYCLE
21 error errno 1
22 error react-redux-starter-kit@1.0.0 pactTest: `export NODE_ENV=pactTest && jest --testRegex "/*(.test.pact.ts)" --runInBand --setupFiles ./pactSetup.ts --setupTestFrameworkScriptFile ./pactTestWrapper.ts`
22 error Exit status 1
23 error Failed at the react-redux-starter-kit@1.0.0 pactTest script.
更新
在 test.pact 文件中注释掉提供程序设置逻辑并重新 运行 npm run pactTest
后,我得到以下信息:
console.error node_modules/@pact-foundation/pact/pact.js:110
Pact verification failed!
console.error node_modules/@pact-foundation/pact/pact.js:111
Actual interactions do not match expected interactions for mock MockService.
Missing requests:
GET /frontoffice/api/liquidity-pool/get-total-payout
See /Users/leongaban/projects/trade.io/tradeio-front/logs/mockserver-integration.log for details.
和我更新的模拟服务器-intergration.log
I, [2018-09-19T14:12:19.128823 #82330] INFO -- : Registered expected interaction GET /frontoffice/api/liquidity-pool/get-total-payout
D, [2018-09-19T14:12:19.129127 #82330] DEBUG -- : {
"description": "a GET request with a user id",
"request": {
"method": "GET",
"path": "/frontoffice/api/liquidity-pool/get-total-payout",
"headers": {
"Accept": "application/json"
}
},
"response": {
"status": 200,
"headers": {
"Content-Type": "application/json"
},
"body": {
"total_payout": 100.21
}
}
}
W, [2018-09-19T14:12:19.139198 #82330] WARN -- : Verifying - actual interactions do not match expected interactions.
Missing requests:
GET /frontoffice/api/liquidity-pool/get-total-payout
W, [2018-09-19T14:12:19.139254 #82330] WARN -- : Missing requests:
GET /frontoffice/api/liquidity-pool/get-total-payout
我可以指出的几个问题:
您似乎声明并启动了一个 pact 模拟服务器两次:在 src/pactSetup.ts
文件中以及在 TotalPayout.test.pact.ts
中,我不确定这是否是您的意图做。您可能希望避免在 TotalPayout 测试中声明提供者,而是您已经在全局范围内拥有 provider
对象作为测试框架设置文件的一部分。
在代码 apiPayout.ts
中,您指的是端点 URL,但是它向哪个端口发送请求?这个 API 调用最终应该被你正在启动的协议模拟提供者捕获。如果您调用的端口与模拟提供程序正在侦听的端口不同,您将永远无法访问它。
一个小吹毛求疵:/frontoffice/api/get-total-payout
不是RESTful。您希望避免在 API 中包含 "get" 等动词,并为此使用正确的 HTTP 方法 (GET)。
不确定这是否是您的问题,但我的 writePact 和 finalize 顺序错了。我有:
afterAll(async () => {
await provider.finalize()
await provider.writePact()
})
而不是正确的顺序:
afterAll(async () => {
await provider.writePact()
await provider.finalize()
})
预期: 运行 npm run pactTest
应生成协议文件 (JSON).
结果: 我收到 Unable to connect
错误。
Pact.io JavaScript implementation guide.
Pact.io Typescript test example.
感谢任何关于我做错的想法或想法:)
错误
FAIL src/services/api/TotalPayout.test.pact.ts The API getUsersTotalPayout ✕ Should call getUsersTotalPayout and return an object with the total_payout (45ms)
● The API › getUsersTotalPayout › Should call getUsersTotalPayout and return an object with the total_payout
PopsicleError: Unable to connect to "http://127.0.0.1:12345/interactions" Caused by: Error: connect ECONNREFUSED 127.0.0.1:12345
at Request.Object.<anonymous>.Request.error (node_modules/popsicle/src/request.ts:91:12) at ClientRequest.<anonymous> (node_modules/popsicle/src/index.ts:218:31)
package.json 脚本:
"pactTest": "export NODE_ENV=pactTest && jest --testRegex \"/*(.test.pact.ts)\" --runInBand --setupFiles ./pactSetup.ts --setupTestFrameworkScriptFile ./pactTestWrapper.ts",
我的src/pactSetup.ts文件
// @ts-ignore
import path from 'path';
import { Pact } from '@pact-foundation/pact/pact';
// @ts-ignore
global.provider = new Pact({
port: 1234,
log: path.resolve(process.cwd(), 'logs', 'mockserver-integration.log'),
dir: path.resolve(process.cwd(), 'pacts'),
spec: 2,
cors: true,
pactfileWriteMode: 'update',
consumer: 'Exchange',
provider: 'LP Service'
});
我的src/pactTestWrapper.ts
jasmine.DEFAULT_TIMEOUT_INTERVAL = 10000; // This is to give the pact mock server time to start
// @ts-ignore
beforeAll(() => provider.setup()); // Create mock provider
// @ts-ignore
afterEach(() => provider.verify()); // Ensure the mock provider verifies expected interactions for each test
// @ts-ignore
afterAll(() => provider.finalize()); // Tear down the mock and write the pact
测试:src/services/api/TotalPayout.test.pact.ts
// @ts-ignore
import path from 'path';
import { Pact } from '@pact-foundation/pact';
import { getTotalPayout } from './apiPayout';
const port = 12345;
const endpoint = '/frontoffice/api/get-total-payout';
const EXPECTED_BODY = {
total_payout: 100.21,
};
const userId = 'foo';
const provider = new Pact({
port,
log: path.resolve(process.cwd(), 'logs', 'mockserver-integration.log'),
dir: path.resolve(process.cwd(), 'pacts'),
spec: 2,
consumer: 'Exchange',
provider: 'LP Service',
pactfileWriteMode: 'merge'
});
describe('The API', () => {
// Copy this block once per interaction under test
describe('getUsersTotalPayout', () => {
beforeEach(() => {
const interaction = {
uponReceiving: 'a GET request with a user id',
withRequest: {
method: 'GET',
path: endpoint,
headers: {
Accept: 'application/json',
},
},
willRespondWith: {
status: 200,
headers: {
'Content-Type': 'application/json'
},
body: EXPECTED_BODY
},
};
// @ts-ignore
return provider.addInteraction(interaction);
});
// add expectations
it('Should call getUsersTotalPayout and return an object with the total_payout', done => {
getTotalPayout(userId)
.then((response: any) => {
expect(response).toEqual(EXPECTED_BODY);
})
.then(done);
});
});
});
api服务文件apiPayout.ts
// @ts-ignore
import axios, * as others from 'axios';
const endpoint = '/frontoffice/api/';
export const getTotalPayout = async (userId: string) => {
const response = await axios.get(`${endpoint}get-total-payout`, { params: userId });
return response.data;
};
来自模拟服务器-integration.log
I, [2018-09-19T11:07:41.259437 #79922] INFO -- : Verifying - interactions matched
I, [2018-09-19T11:07:41.264440 #79922] INFO -- : Cleared interactions
来自调试日志
20 error code ELIFECYCLE
21 error errno 1
22 error react-redux-starter-kit@1.0.0 pactTest: `export NODE_ENV=pactTest && jest --testRegex "/*(.test.pact.ts)" --runInBand --setupFiles ./pactSetup.ts --setupTestFrameworkScriptFile ./pactTestWrapper.ts`
22 error Exit status 1
23 error Failed at the react-redux-starter-kit@1.0.0 pactTest script.
更新
在 test.pact 文件中注释掉提供程序设置逻辑并重新 运行 npm run pactTest
后,我得到以下信息:
console.error node_modules/@pact-foundation/pact/pact.js:110 Pact verification failed!
console.error node_modules/@pact-foundation/pact/pact.js:111 Actual interactions do not match expected interactions for mock MockService.
Missing requests: GET /frontoffice/api/liquidity-pool/get-total-payout
See /Users/leongaban/projects/trade.io/tradeio-front/logs/mockserver-integration.log for details.
和我更新的模拟服务器-intergration.log
I, [2018-09-19T14:12:19.128823 #82330] INFO -- : Registered expected interaction GET /frontoffice/api/liquidity-pool/get-total-payout
D, [2018-09-19T14:12:19.129127 #82330] DEBUG -- : {
"description": "a GET request with a user id",
"request": {
"method": "GET",
"path": "/frontoffice/api/liquidity-pool/get-total-payout",
"headers": {
"Accept": "application/json"
}
},
"response": {
"status": 200,
"headers": {
"Content-Type": "application/json"
},
"body": {
"total_payout": 100.21
}
}
}
W, [2018-09-19T14:12:19.139198 #82330] WARN -- : Verifying - actual interactions do not match expected interactions.
Missing requests:
GET /frontoffice/api/liquidity-pool/get-total-payout
W, [2018-09-19T14:12:19.139254 #82330] WARN -- : Missing requests:
GET /frontoffice/api/liquidity-pool/get-total-payout
我可以指出的几个问题:
您似乎声明并启动了一个 pact 模拟服务器两次:在
src/pactSetup.ts
文件中以及在TotalPayout.test.pact.ts
中,我不确定这是否是您的意图做。您可能希望避免在 TotalPayout 测试中声明提供者,而是您已经在全局范围内拥有provider
对象作为测试框架设置文件的一部分。在代码
apiPayout.ts
中,您指的是端点 URL,但是它向哪个端口发送请求?这个 API 调用最终应该被你正在启动的协议模拟提供者捕获。如果您调用的端口与模拟提供程序正在侦听的端口不同,您将永远无法访问它。一个小吹毛求疵:
/frontoffice/api/get-total-payout
不是RESTful。您希望避免在 API 中包含 "get" 等动词,并为此使用正确的 HTTP 方法 (GET)。
不确定这是否是您的问题,但我的 writePact 和 finalize 顺序错了。我有:
afterAll(async () => {
await provider.finalize()
await provider.writePact()
})
而不是正确的顺序:
afterAll(async () => {
await provider.writePact()
await provider.finalize()
})