Skip to main content

Registering functions

During verification, ContractCase needs to be able to invoke the real implementation of each function named in the contract. You provide these with registerFunction, called on the verifier before running the verification.

The first argument is the function name from the contract (the functionName the consumer used when defining the interaction), and the second is the implementation to invoke:

verifyContract(
{
providerName: 'function execution',
},
(verifier) => {
verifier.registerFunction('zeroArgs', () => {});
verifier.registerFunction('concatenate', (a, b) => `${a}${b}`);
},
);

If the contract contains an interaction for a function that hasn't been registered, ContractCase fails the verification with a configuration error telling you which function name it was looking for.

Argument and return value serialisation

Arguments and return values are JSON-serialised when they cross the boundary between ContractCase and your code. In dynamically typed languages like typescript, this is handled for you. In Java, registered functions receive each argument as a JSON string and must return a JSON string, so you may need a small adapter around the function under test to parse the arguments and serialise the result. For example, the convertJsonIntegerArg adapter used above is:

// With Typescript/Javascript, arguments and return values
// are marshalled for you, so no adapter is needed

Functions that throw

If the interaction was defined with a throwing variant (see defining function call interactions), ContractCase invokes your registered function and expects it to throw. The class name of the thrown error is compared with the errorClassName in the contract.

If the interaction also describes errorInternals, the thrown error is serialised and its content is compared with the errorInternals matcher:

  • In Typescript, the error internals are the error's own enumerable properties (excluding the standard name, message, stack and cause).
  • In Java, the exception is serialised with Jackson, so the error internals contain any public getters on the exception class (the standard Throwable properties such as the stack trace, cause and message are excluded). If your exception has properties that can't be serialised, exclude them with Jackson annotations such as @JsonIgnore.

State handlers

If any interactions in the contract have states, you provide state handlers in exactly the same way as for HTTP server verification. This is often how you set up the data that a registered function needs to return the expected values.