Replies: 2 comments 6 replies
-
Hey! Does the server that you are starting, have data for id it now, you will want a state handler, for given a product with id exists (ideally as a state parameter) and you can use this on your provider side to ensure you have the specific id resource setup for the test or just ensure your provider repository has a product with |
Beta Was this translation helpful? Give feedback.
-
Thanks for looking into this. I've done a rewrite as I want to verify against the broker not locally but getting the same result.
There were 1 pact failures Rewritten code here
|
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
I can create a pact and publish it but having trouble verifying it.
Any help is appreciated.
Code as follows...
import * as path from 'path';
import { PactV3, MatchersV3, LogLevel, Verifier} from '@pact-foundation/pact';
const { Publisher } = require('@pact-foundation/pact-node');
import * as express from 'express';
const app = express();
const PORT = 8081;
app.listen(PORT, () => {
console.log('User Profile Service listening on http://localhost:8081');
});
let opts = {
providerBaseUrl:'http://localhost:8081',
pactUrls: [ path.resolve(process.cwd(), './pacts/User Web-User API.json') ],
};
new Verifier(opts).verifyProvider().then( async () => {
console.log('Pact verification complete!');
}).catch((error) => {
console.error('Pact verification failed: ', error);
process.exit(1);
});
Log
`andrewchambers@Andrews-MacBook-Pro typescript % npm run test
User Profile Service listening on http://localhost:8081
2023-05-10T10:31:49.353646Z DEBUG ThreadId(01) pact_ffi::verifier: pact_ffi::verifier::pactffi_verifier_new_for_application FFI function invoked
2023-05-10T10:31:49.353818Z DEBUG ThreadId(01) pact_ffi::verifier: pact_ffi::verifier::pactffi_verifier_set_provider_info FFI function invoked
2023-05-10T10:31:49.353882Z DEBUG ThreadId(01) pact_ffi::verifier: pact_ffi::verifier::pactffi_verifier_set_provider_state FFI function invoked
2023-05-10T10:31:49.353904Z DEBUG ThreadId(01) pact_ffi::verifier: pact_ffi::verifier::pactffi_verifier_set_verification_options FFI function invoked
2023-05-10T10:31:49.354467Z DEBUG ThreadId(01) pact_ffi::verifier: pact_ffi::verifier::pactffi_verifier_add_file_source FFI function invoked
2023-05-10T10:31:49.354643Z DEBUG ThreadId(02) pact_ffi::verifier: pact_ffi::verifier::pactffi_verifier_execute FFI function invoked
2023-05-10T10:31:49.354653Z DEBUG ThreadId(02) pact_ffi::verifier::handle: Pact source to verify = File(/Users/andrewchambers/Dev/pact-js-poc/examples/v3/typescript/pacts/User Web-User API.json)
2023-05-10T10:31:49.354875Z DEBUG ThreadId(02) pact_plugin_driver::catalogue_manager: Updated catalogue entries:
core/content-generator/binary
core/content-generator/json
core/content-matcher/json
core/content-matcher/multipart-form-data
core/content-matcher/text
core/content-matcher/xml
2023-05-10T10:31:49.354901Z DEBUG ThreadId(02) pact_plugin_driver::catalogue_manager: Updated catalogue entries:
core/matcher/v1-equality
core/matcher/v2-max-type
core/matcher/v2-min-type
core/matcher/v2-minmax-type
core/matcher/v2-regex
core/matcher/v2-type
core/matcher/v3-content-type
core/matcher/v3-date
core/matcher/v3-datetime
core/matcher/v3-decimal-type
core/matcher/v3-includes
core/matcher/v3-integer-type
core/matcher/v3-null
core/matcher/v3-number-type
core/matcher/v3-time
core/matcher/v4-array-contains
core/matcher/v4-equals-ignore-order
core/matcher/v4-max-equals-ignore-order
core/matcher/v4-min-equals-ignore-order
core/matcher/v4-minmax-equals-ignore-order
core/matcher/v4-not-empty
core/matcher/v4-semver
The Users API
get /users/:id
2023-05-10T10:31:49.357391Z DEBUG ThreadId(01) pact_plugin_driver::catalogue_manager: Updated catalogue entries:
core/transport/http
core/transport/https
2023-05-10T10:31:49.357529Z DEBUG ThreadId(01) pact_mock_server::mock_server: Started mock server on 127.0.0.1:62415
2023-05-10T10:31:49.361628Z DEBUG tokio-runtime-worker hyper::proto::h1::io: parsed 4 headers
2023-05-10T10:31:49.361644Z DEBUG tokio-runtime-worker hyper::proto::h1::conn: incoming body is empty
2023-05-10T10:31:49.361650Z DEBUG tokio-runtime-worker pact_mock_server::hyper_server: Creating pact request from hyper request
2023-05-10T10:31:49.361652Z DEBUG tokio-runtime-worker pact_mock_server::hyper_server: Extracting query from uri /users/1
2023-05-10T10:31:49.361677Z INFO tokio-runtime-worker pact_mock_server::hyper_server: Received request HTTP Request ( method: GET, path: /users/1, query: None, headers: Some({"host": ["127.0.0.1:62415"], "connection": ["close"], "accept": ["application/json"], "user-agent": ["axios/0.27.2"]}), body: Empty )
2023-05-10T10:31:49.361710Z INFO tokio-runtime-worker pact_matching: comparing to expected HTTP Request ( method: GET, path: /users/1, query: None, headers: None, body: Missing )
2023-05-10T10:31:49.361713Z DEBUG tokio-runtime-worker pact_matching: body: ''
2023-05-10T10:31:49.361714Z DEBUG tokio-runtime-worker pact_matching: matching_rules: MatchingRules { rules: {PATH: MatchingRuleCategory { name: PATH, rules: {} }} }
2023-05-10T10:31:49.361717Z DEBUG tokio-runtime-worker pact_matching: generators: Generators { categories: {} }
2023-05-10T10:31:49.361727Z DEBUG tokio-runtime-worker pact_matching::matchers: String -> String: comparing '/users/1' to '/users/1' ==> true cascaded=false matcher=Equality
2023-05-10T10:31:49.361874Z DEBUG tokio-runtime-worker pact_matching: expected content type = '/', actual content type = '/'
2023-05-10T10:31:49.361896Z DEBUG tokio-runtime-worker pact_matching: content type header matcher = 'RuleList { rules: [], rule_logic: And, cascaded: false }'
2023-05-10T10:31:49.361904Z DEBUG tokio-runtime-worker pact_matching: --> Mismatches: []
2023-05-10T10:31:49.361930Z DEBUG tokio-runtime-worker pact_mock_server::hyper_server: Test context = {"mockServer": Object {"href": String("http://127.0.0.1:62415"), "port": Number(62415)}}
2023-05-10T10:31:49.361941Z INFO tokio-runtime-worker pact_mock_server::hyper_server: Request matched, sending response HTTP Response ( status: 200, headers: Some({"content-type": ["application/json"]}), body: Present(31 bytes, application/json) )
2023-05-10T10:31:49.361946Z DEBUG tokio-runtime-worker pact_mock_server::hyper_server: body: '{"id":1,"name":"Homer Simpson"}'
2023-05-10T10:31:49.361972Z DEBUG tokio-runtime-worker hyper::proto::h1::io: flushed 383 bytes
2023-05-10T10:31:49.364161Z DEBUG ThreadId(01) pact_ffi::mock_server::handles: pact_ffi::mock_server::handles::pactffi_pact_handle_write_file FFI function invoked
2023-05-10T10:31:49.364202Z DEBUG ThreadId(01) pact_models::pact: Merging pact with file "./pacts/User Web-User API.json"
2023-05-10T10:31:49.364338Z WARN ThreadId(01) pact_models::pact: Note: Existing pact is an older specification version (V3), and will be upgraded
2023-05-10T10:31:49.364600Z DEBUG ThreadId(01) pact_matching::metrics: Could not get the tokio runtime, will not send metrics - there is no reactor running, must be called from the context of a Tokio 1.x runtime
2023-05-10T10:31:49.364608Z DEBUG ThreadId(01) pact_mock_server::server_manager: Shutting down mock server with ID be53fb41-b9f5-4c59-ae7b-c3fc58a2c928 - MockServerMetrics { requests: 1 }
2023-05-10T10:31:49.364615Z DEBUG ThreadId(01) pact_mock_server::mock_server: Mock server be53fb41-b9f5-4c59-ae7b-c3fc58a2c928 shutdown - MockServerMetrics { requests: 1 }
2023-05-10T10:31:49.364637Z DEBUG tokio-runtime-worker hyper::server::shutdown: signal received, starting graceful shutdown
✔ returns the requested user
Publish pact
[2023-05-10 10:31:49.367 +0000] INFO (90521 on Andrews-MacBook-Pro.local): [email protected]: Publishing pacts to broker at: https://fluxpoc.pactflow.io
✔ should publish pact to pactflow
2 passing (24ms)
[22:31:49.348] INFO (90521): [email protected]: Verifying provider
[22:31:49.352] INFO (90521): [email protected]: Verifying Pacts.
[22:31:49.352] INFO (90521): [email protected]: Verifying Pact Files
[22:31:49.352] WARN (90521): [email protected]: The pact native core has already been initialised at log level 'Debug'
[22:31:49.352] WARN (90521): [email protected]: The new requested log level 'info' will be ignored
2023-05-10T10:31:49.581408Z DEBUG ThreadId(02) verify_interaction{interaction="a request to get a user"}: pact_verifier: Executing provider states
2023-05-10T10:31:49.581433Z INFO ThreadId(02) verify_interaction{interaction="a request to get a user"}: pact_verifier: Running setup provider state change handler 'a user with ID 1 exists' for 'a request to get a user'
2023-05-10T10:31:49.758620Z DEBUG ThreadId(02) verify_interaction{interaction="a request to get a user"}: pact_verifier::provider_client: Sending HTTP Request ( method: POST, path: /, query: None, headers: Some({"Content-Type": ["application/json"]}), body: Present(64 bytes, application/json) ) to state change handler
2023-05-10T10:31:49.758723Z DEBUG ThreadId(02) verify_interaction{interaction="a request to get a user"}: hyper::client::connect::http: connecting to 127.0.0.1:62414
2023-05-10T10:31:49.759012Z DEBUG ThreadId(02) verify_interaction{interaction="a request to get a user"}: hyper::client::connect::http: connected to 127.0.0.1:62414
2023-05-10T10:31:49.759180Z DEBUG tokio-runtime-worker hyper::proto::h1::io: flushed 213 bytes
2023-05-10T10:31:49.770807Z DEBUG tokio-runtime-worker hyper::proto::h1::io: parsed 6 headers
2023-05-10T10:31:49.770826Z DEBUG tokio-runtime-worker hyper::proto::h1::conn: incoming body is empty
2023-05-10T10:31:49.770857Z DEBUG ThreadId(02) verify_interaction{interaction="a request to get a user"}: hyper::client::pool: pooling idle connection for ("http", 127.0.0.1:62414)
2023-05-10T10:31:49.770881Z DEBUG ThreadId(02) verify_interaction{interaction="a request to get a user"}: pact_verifier::provider_client: State change request: Response { url: Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(62414), path: "/_pactSetup", query: None, fragment: None }, status: 200, headers: {"x-powered-by": "Express", "content-type": "application/json; charset=utf-8", "date": "Wed, 10 May 2023 10:31:49 GMT", "connection": "keep-alive", "keep-alive": "timeout=5", "content-length": "0"} }
2023-05-10T10:31:49.770954Z DEBUG ThreadId(02) verify_interaction{interaction="a request to get a user"}: pact_verifier: State Change: "ProviderState { name: "a user with ID 1 exists", params: {} }" -> Ok({})
2023-05-10T10:31:49.770964Z INFO ThreadId(02) verify_interaction{interaction="a request to get a user"}: pact_verifier: Running provider verification for 'a request to get a user'
2023-05-10T10:31:49.770980Z DEBUG ThreadId(02) verify_interaction{interaction="a request to get a user"}: pact_verifier: Verifying a HTTP interaction
2023-05-10T10:31:49.770997Z INFO ThreadId(02) verify_interaction{interaction="a request to get a user"}: pact_verifier::provider_client: Sending request to provider at http://127.0.0.1:62414/
2023-05-10T10:31:49.770999Z DEBUG ThreadId(02) verify_interaction{interaction="a request to get a user"}: pact_verifier::provider_client: Provider details = ProviderInfo { name: "provider", protocol: "http", host: "127.0.0.1", port: Some(62414), path: "/", transports: [ProviderTransport { transport: "http", port: Some(62414), path: Some("/"), scheme: None }] }
2023-05-10T10:31:49.771003Z INFO ThreadId(02) verify_interaction{interaction="a request to get a user"}: pact_verifier::provider_client: Sending request HTTP Request ( method: GET, path: /users/1, query: None, headers: None, body: Missing )
2023-05-10T10:31:49.771006Z DEBUG ThreadId(02) verify_interaction{interaction="a request to get a user"}: pact_verifier::provider_client: body:
2023-05-10T10:31:49.771028Z DEBUG ThreadId(02) verify_interaction{interaction="a request to get a user"}: hyper::client::pool: reuse idle connection for ("http", 127.0.0.1:62414)
<title>Error</title>2023-05-10T10:31:49.771093Z DEBUG tokio-runtime-worker hyper::proto::h1::io: flushed 93 bytes
2023-05-10T10:31:49.775897Z DEBUG tokio-runtime-worker hyper::proto::h1::io: parsed 7 headers
2023-05-10T10:31:49.775908Z DEBUG tokio-runtime-worker hyper::proto::h1::conn: incoming body is content-length (146 bytes)
2023-05-10T10:31:49.775923Z DEBUG tokio-runtime-worker hyper::proto::h1::conn: incoming body completed
2023-05-10T10:31:49.775944Z DEBUG ThreadId(02) verify_interaction{interaction="a request to get a user"}: pact_verifier::provider_client: Received native response: Response { url: Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(62414), path: "/users/1", query: None, fragment: None }, status: 404, headers: {"x-powered-by": "Express", "content-security-policy": "default-src 'none'", "x-content-type-options": "nosniff", "content-type": "text/html; charset=utf-8", "content-length": "146", "date": "Wed, 10 May 2023 10:31:49 GMT", "connection": "close"} }
2023-05-10T10:31:49.775985Z INFO ThreadId(02) verify_interaction{interaction="a request to get a user"}: pact_verifier::provider_client: Received response: HTTP Response ( status: 404, headers: Some({"content-length": ["146"], "x-powered-by": ["Express"], "date": ["Wed", "10 May 2023 10:31:49 GMT"], "connection": ["close"], "content-security-policy": ["default-src 'none'"], "content-type": ["text/html; charset=utf-8"], "x-content-type-options": ["nosniff"]}), body: Present(146 bytes, text/html;charset=utf-8) )
2023-05-10T10:31:49.775995Z DEBUG ThreadId(02) verify_interaction{interaction="a request to get a user"}: pact_verifier::provider_client: body:
2023-05-10T10:31:49.776005Z INFO ThreadId(02) verify_interaction{interaction="a request to get a user"}: pact_matching: comparing to expected response: HTTP Response ( status: 200, headers: Some({"content-type": ["application/json"]}), body: Present(31 bytes) )
2023-05-10T10:31:49.776123Z DEBUG ThreadId(02) verify_interaction{interaction="a request to get a user"}: pact_matching: expected content type = 'application/json', actual content type = 'text/html;charset=utf-8'
2023-05-10T10:31:49.776138Z DEBUG ThreadId(02) verify_interaction{interaction="a request to get a user"}: pact_matching: content type header matcher = 'RuleList { rules: [], rule_logic: And, cascaded: false }'
2023-05-10T10:31:49.776192Z INFO ThreadId(02) verify_interaction{interaction="a request to get a user"}: pact_verifier: Running teardown provider state change handler 'a user with ID 1 exists' for 'a request to get a user'
[22:31:49.770] DEBUG (90521): [email protected]: setting up state '{"action":"setup","params":{},"state":"a user with ID 1 exists"}'
[22:31:49.770] WARN (90521): [email protected]: no state handler found for state: "a user with ID 1 exists"
[22:31:49.771] DEBUG (90521): [email protected]: Proxying GET: /users/1
2023-05-10T10:31:49.958223Z DEBUG ThreadId(02) verify_interaction{interaction="a request to get a user"}: pact_verifier::provider_client: Sending HTTP Request ( method: POST, path: /, query: None, headers: Some({"Content-Type": ["application/json"]}), body: Present(67 bytes, application/json) ) to state change handler
2023-05-10T10:31:49.958290Z DEBUG ThreadId(02) verify_interaction{interaction="a request to get a user"}: hyper::client::connect::http: connecting to 127.0.0.1:62414
2023-05-10T10:31:49.958563Z DEBUG ThreadId(02) verify_interaction{interaction="a request to get a user"}: hyper::client::connect::http: connected to 127.0.0.1:62414
2023-05-10T10:31:49.958644Z DEBUG tokio-runtime-worker hyper::proto::h1::io: flushed 216 bytes
2023-05-10T10:31:49.959702Z DEBUG tokio-runtime-worker hyper::proto::h1::io: parsed 6 headers
2023-05-10T10:31:49.959718Z DEBUG tokio-runtime-worker hyper::proto::h1::conn: incoming body is empty
2023-05-10T10:31:49.959754Z DEBUG ThreadId(02) verify_interaction{interaction="a request to get a user"}: hyper::client::pool: pooling idle connection for ("http", 127.0.0.1:62414)
2023-05-10T10:31:49.959777Z DEBUG ThreadId(02) verify_interaction{interaction="a request to get a user"}: pact_verifier::provider_client: State change request: Response { url: Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(62414), path: "/_pactSetup", query: None, fragment: None }, status: 200, headers: {"x-powered-by": "Express", "content-type": "application/json; charset=utf-8", "date": "Wed, 10 May 2023 10:31:49 GMT", "connection": "keep-alive", "keep-alive": "timeout=5", "content-length": "0"} }
2023-05-10T10:31:49.959823Z DEBUG ThreadId(02) verify_interaction{interaction="a request to get a user"}: pact_verifier: State Change: "ProviderState { name: "a user with ID 1 exists", params: {} }" -> Ok({})
2023-05-10T10:31:49.959959Z WARN ThreadId(02) pact_matching::metrics:
Please note:
We are tracking events anonymously to gather important usage statistics like Pact version and operating system. To disable tracking, set the 'PACT_DO_NOT_TRACK' environment variable to 'true'.
2023-05-10T10:31:49.964671Z DEBUG ThreadId(02) pact_matching::metrics: Sending event to GA - {"t": "event", "ev": "1", "av": "13.13.5", "cd2": "unknown", "cd3": "macos-aarch64", "v": "1", "ds": "client", "ea": "Completed", "an": "pact-core", "tid": "UA-117778936-1", "aip": "true", "el": "Pacts verified", "cid": "03070114ab91bfb5c930841efa12dfee", "aid": "pact-core", "cd6": "pact_ffi", "cd7": "1.0.4", "ec": "ProviderTest"}
[22:31:49.959] DEBUG (90521): [email protected]: setting up state '{"action":"teardown","params":{},"state":"a user with ID 1 exists"}'
2023-05-10T10:31:50.140715Z DEBUG tokio-runtime-worker hyper::client::connect::dns: resolving host="www.google-analytics.com"
2023-05-10T10:31:50.150767Z DEBUG ThreadId(02) hyper::client::connect::http: connecting to 142.250.204.14:443
2023-05-10T10:31:50.193117Z DEBUG ThreadId(02) hyper::client::connect::http: connected to 142.250.204.14:443
2023-05-10T10:31:50.331370Z DEBUG ThreadId(02) h2::client: binding client connection
2023-05-10T10:31:50.331394Z DEBUG ThreadId(02) h2::client: client connection bound
2023-05-10T10:31:50.331404Z DEBUG ThreadId(02) h2::codec::framed_write: send frame=Settings { flags: (0x0), enable_push: 0, initial_window_size: 2097152, max_frame_size: 16384 }
2023-05-10T10:31:50.331470Z DEBUG tokio-runtime-worker Connection{peer=Client}: h2::codec::framed_write: send frame=WindowUpdate { stream_id: StreamId(0), size_increment: 5177345 }
2023-05-10T10:31:50.331485Z DEBUG ThreadId(02) hyper::client::pool: pooling idle connection for ("https", www.google-analytics.com)
2023-05-10T10:31:50.331562Z DEBUG tokio-runtime-worker Connection{peer=Client}: h2::codec::framed_write: send frame=Headers { stream_id: StreamId(1), flags: (0x4: END_HEADERS) }
2023-05-10T10:31:50.331584Z DEBUG tokio-runtime-worker Connection{peer=Client}: h2::codec::framed_write: send frame=Data { stream_id: StreamId(1), flags: (0x1: END_STREAM) }
2023-05-10T10:31:50.416387Z DEBUG tokio-runtime-worker Connection{peer=Client}: h2::codec::framed_read: received frame=Settings { flags: (0x0), max_concurrent_streams: 100, initial_window_size: 1048576, max_header_list_size: 65536 }
2023-05-10T10:31:50.416434Z DEBUG tokio-runtime-worker Connection{peer=Client}: h2::codec::framed_write: send frame=Settings { flags: (0x1: ACK) }
2023-05-10T10:31:50.416443Z DEBUG tokio-runtime-worker Connection{peer=Client}: h2::codec::framed_read: received frame=WindowUpdate { stream_id: StreamId(0), size_increment: 983041 }
2023-05-10T10:31:50.416449Z DEBUG tokio-runtime-worker Connection{peer=Client}: h2::codec::framed_read: received frame=Settings { flags: (0x1: ACK) }
2023-05-10T10:31:50.416452Z DEBUG tokio-runtime-worker Connection{peer=Client}: h2::proto::settings: received settings ACK; applying Settings { flags: (0x0), enable_push: 0, initial_window_size: 2097152, max_frame_size: 16384 }
2023-05-10T10:31:50.510242Z DEBUG tokio-runtime-worker Connection{peer=Client}: h2::codec::framed_read: received frame=Headers { stream_id: StreamId(1), flags: (0x4: END_HEADERS) }
Verifying a pact between User Web and User API
a request to get a user
Given a user with ID 1 exists
returns a response which
has status code 200 (FAILED)
includes headers
"content-type" with value "application/json" (FAILED)
has a matching body (FAILED)
Failures:
1.1) has a matching body
expected 'application/json' body but was 'text/html;charset=utf-8'
1.2) has status code 200
expected 200 but was 404
1.3) includes header 'content-type' with value 'application/json'
Expected header 'content-type' to have value 'application/json' but was 'text/html; charset=utf-8'
There were 1 pact failures
2023-05-10T10:31:50.510465Z DEBUG tokio-runtime-worker Connection{peer=Client}: h2::codec::framed_write: send frame=GoAway { error_code: NO_ERROR, last_stream_id: StreamId(0) }
2023-05-10T10:31:50.510538Z DEBUG ThreadId(02) pact_plugin_driver::plugin_manager: Shutting down all plugins
2023-05-10T10:31:50.510546Z DEBUG tokio-runtime-worker Connection{peer=Client}: h2::proto::connection: Connection::poll; connection error error=GoAway(b"", NO_ERROR, Library)
2023-05-10T10:31:50.511224Z DEBUG ThreadId(01) pact_ffi::verifier: pact_ffi::verifier::pactffi_verifier_shutdown FFI function invoked
Pact verification failed: Error: Verfication failed
at /Users/andrewchambers/Dev/pact-js-poc/examples/v3/typescript/node_modules/@pact-foundation/pact-core/src/verifier/nativeVerifier.ts:52:20
[22:31:50.511] DEBUG (90521): [email protected]: shutting down verifier with handle 0
[22:31:50.511] DEBUG (90521): [email protected]: response from verifier: null, 1
[22:31:50.511] ERROR (90521): [email protected]: Verification unsuccessful`
Beta Was this translation helpful? Give feedback.
All reactions