Zied Bejaoui
04/09/2024, 7:27 AMdescribe("receive transfer event", () => {
it("accepts a transfer", () => {
return messagePact
.given("a new transfer")
.expectsToReceive(
"Action handlers consumes a new message in Kafka topic",
) // test description is the contract identifier and should match on cosumer side
.withContent(transferBodyExpectation)
.verify(asynchronousBodyHandler(actionHandler)); //existing SUT handler function
});
});
});
Here are my questions please :
1-Is my test strategy correct/acceptable according to contract testing?
2-When running my tests I have noticed this non blocking error, I am not sure what this error means :
ERROR (29508): pact@12.4.0: no handler found for message Action handlers consumes a new message in Kafka topic
3-Finally, my provider test is failing with this message :
1.1) has a matching body
$ -> Actual map is missing the following keys: body
I am not sure why it's complaining about key body when I have set it in expected body :
const transferBodyExpectation = {
from: like("***********"),
body: {
id: like("************"),
originator: { "*************") },
beneficiary: { "*************") },
asset: like("*************"),
amountSubunits: like("*************"),
The message I am expecting from Kafka is this one : Note that I am ignoring some attributes such as to, type because they are not added by action handler map function but added by another protocol that I am not testing for now.
{
"id": "***********",
"from": "***********",
"to": [
"***********"
],
"type": "***********",
"body": {
Matt (pactflow.io / pact-js / pact-go)
Zied Bejaoui
04/09/2024, 7:36 AMZied Bejaoui
04/09/2024, 7:36 AMZied Bejaoui
04/09/2024, 7:36 AMdescribe("receive transfer event", () => {
it("accepts a transfer", () => {
return messagePact
.given("a new transfer")
.expectsToReceive("a request for a new transfer") // test description is the contract identifier and should match on ion cosumer side
.withContent(transferBodyExpectation)
.verify(asynchronousBodyHandler(actionHandler));
});
});
});
Slackbot
04/09/2024, 7:36 AMZied Bejaoui
04/09/2024, 7:37 AMdescribe("a request for a new transfer", () => {
// test description is the contract identifier and should match on ion cosumer side
it("sends a valid transfer", () => {
return p.verify();
});
});
});
Matt (pactflow.io / pact-js / pact-go)
Matt (pactflow.io / pact-js / pact-go)
Matt (pactflow.io / pact-js / pact-go)
Zied Bejaoui
04/09/2024, 9:22 AMMatt (pactflow.io / pact-js / pact-go)
Zied Bejaoui
04/09/2024, 12:10 PMZied Bejaoui
04/09/2024, 12:12 PM) Verifying a pact between MyActionHandlerConsumer and MyTransferProvider Given a new transfer - a request for a new transfer
1.1) has a matching body
$ -> Actual map is missing the following keys: agents, amountSubunits, asset, beneficiary, originator
-{
"agents": [
{
"@id": "***********************",
"for": "***********************",
"role": "***********************"
}
],
"amountSubunits": "***********************",
"asset": "***********************",
"beneficiary": {
"***********************"
},
"originator": {
"***********************"
}
}
+{}
Zied Bejaoui
04/09/2024, 4:39 PMactual message = AsynchronousMessage { id: None, key: None, description: "Asynchronous/Message Interaction", provider_states: [], contents: MessageContents { contents: Present(b"{}", Some(ContentType { main_type: "application", sub_type: "json", attributes: {"charset": "utf-8"}, suffix: None }), None), metadata: {"contentType": String("application/json; charset=utf-8")}, matching_rules: MatchingRules { rules: {} }, generators: Generators { categories: {} } }, comments: {}, pending: false, plugin_config: {}, interaction_markup: InteractionMarkup { markup: "", markup_type: "" }, transport: None }
I can see the message created in Kafka UI topic. still debugging but if someone can help please get in touch.Matt (pactflow.io / pact-js / pact-go)
Matt (pactflow.io / pact-js / pact-go)
I am wondering if this error is simply cause by my test code or my whole setup is incorrect and maybe I should not use an API call as my provider? As the response I get from a post request does not match the message to be consumed by Kafka. The message to be consumed is transformed in between.you should be registering a producer function in a message test, the verifier won’t be talking to an HTTP endpoint for this
Zied Bejaoui
04/10/2024, 8:40 AMdescribe("Transfers provider tests", () => {
const p = new MessageProviderPact({
messageProviders: {
"a request for a new transfer": providerWithMetadata(
//should match expect to receive on consumer side
() => createTransfer("af7625bb-b272-41c8-988a-5372d100346d"), // note this is a post REST API call
{ queue: "" },
),
},
stateHandlers: {
"some state": () => {
// TODO: prepare system useful in order to create a transfer
console.log('State handler: setting up "some state" for interaction');
return Promise.resolve(`state set to create a transfer`);
// we can add VASP creation here
},
},
logLevel: LOG_LEVEL as LogLevel,
provider: "MyTransferProvider",
providerVersion: versionFromGitTag(),
//Broker validation
pactBrokerUrl: "<https://notabene.pactflow.io/>",
pactBrokerToken: process.env.PACT_BROKER_TOKEN || "************",
providerVersionBranch: process.env.GIT_BRANCH || "pact-integration", // use an env var later for the brancg name
publishVerificationResult: true,
// Find _all_ pacts that match the current provider branch
consumerVersionSelectors: [
{
matchingBranch: true,
},
],
});
describe("send a create transfer request", () => {
it("creates a new transfer", () => {
return p.verify();
});
});
});
Zied Bejaoui
04/10/2024, 8:45 AMZied Bejaoui
04/10/2024, 8:45 AMZied Bejaoui
04/10/2024, 8:51 AMMatt (pactflow.io / pact-js / pact-go)
() => createTransfer(“af7625bb-b272-41c8-988a-5372d100346d”), // note this is a post REST API callso
createTransfer(…)
needs to return a JSON blob that matchers whatever is in the consumer contract. If it’s not, then that’s why it will failMatt (pactflow.io / pact-js / pact-go)
I should replace the REST API with the producer function writing into the topic? (edited)yes, that’s correct
Matt (pactflow.io / pact-js / pact-go)
Zied Bejaoui
04/11/2024, 8:05 AMZied Bejaoui
04/11/2024, 10:28 AMexport async function actionHandler(
actions: Stream<object>,
events: (s: Stream<any>) => Stream<any>,
outbox: (s: Stream<any>) => Stream<any>,
) {
............;
.............
.............;
return mergeArray([actionsToEvents, actionsToOutbox]);
This function returns the following type :
(alias) mergeArray<Stream<any>[]>(streams: Stream<any>[]): Stream<any>
import mergeArray
_@param_ streams — array of stream to merge
@returns
stream containing events from all input observables in time order. If two events are simultaneous they will be merged in arbitrary order.
Now when calling the function in asynchronousBodyHandler obviously I have a signature error as the asynchronousBodyHandler expects a (body: AnyJson | Buffer): Promise<unknown>'
and not a 'Promise<Stream<any>>'
So in this case is there a way to still use asynchronousBodyHandler to verify that my consumer can consume the provided message, or is there another function available by PACT that takes streams as a param instead? Or should I implement my own function? (asking that to no implement my own function in case an alternative already exists).Matt (pactflow.io / pact-js / pact-go)
Zied Bejaoui
04/15/2024, 7:16 AMMatt (pactflow.io / pact-js / pact-go)
Zied Bejaoui
04/15/2024, 12:03 PMZied Bejaoui
04/15/2024, 12:04 PMZied Bejaoui
04/15/2024, 12:05 PMZied Bejaoui
04/15/2024, 12:05 PMZied Bejaoui
04/15/2024, 12:24 PMZied Bejaoui
04/15/2024, 12:24 PM