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.
-
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