API testing with TestContainers in Corda - corda

I'm coding a REST API that connects to my Corda Node via Corda RPC. I'm trying to create a mock testing corda network with TestContainers so that I can verify the behaviors of my REST API. I know Corda has official docker image. Is there any guidance on how might I go about implementing this?

I would look at this/divide this into two parts.
Server side testing - Testing your node RPC endpoints.
Client side testing - Testing your rest endpoints.
For the first part, you can use the NodeDriver to write the integration tests. Using the NodeDriver, you can bring up nodes locally to run flows and inspect state updates. The NodeDriver allows you to access the node using RPC endpoints. You can read more about NodeDriver here.
For the second part, you can use something like mockito to mock the RPC calls and test your client logic.
This way you will easily be able to test client and server side.
To do an actual end to end integration test, you will have to start the docker nodes using a script and then you can test the methods from the client code.

Related

PACT - Handling provider service state and running actual provider with mocked or actual database

I am new to PACT and trying to use pact-net for contract testing for a .net microservice. I understand the concept of consumer test which generates a pact file.
There is the concept of a provider state middleware which is responsible for making sure that the provider's state matches the Given() condition in the generated pact.
I am bit confused on the following or how to achieve this:
The provider tests are run against the actual service. So we start the provider service before tests are run. My provider service interacts with a database to store and retrieve records. PACT also mentions that all the dependencies of a service should be stubbed.
So we run the actual provider api that is running against the actual db?
If we running the api against actual db how do we inject the data into the db? Should we be using the provider api's own endpoints to add the Given() data?
If the above is not the correct approach then what is?
All the basic blog articles I have come across do not explain this and usually have examples with no provider states or states that are just some text files on the file system.
Help appreciated.
I'm going to add to Matt's comment, you have three options:
Do your provider test with a connected environment but you will have to do some cleanup manually afterwards and make sure your data is always available in your db or/and the external APIs are always up and running. Simple to write but can be very hard to maintain.
You mock your API calls but call the real database.
You mock all your external dependencies: the API and the DB calls.
For 2) or 3) you will have to have test routes and inject the provider state middleware in your provider test fixture. Then, you can configure provider states to be called to generate in-memory data if solution 3) or add some data-init if you are in solution 2)
You can find an example here: https://github.com/pact-foundation/pact-net/tree/master/Samples/EventApi/Provider.Api.Web.Tests
The provider tests are run against the actual service
Do you mean against a live environment, or the actual service running locally to the unit test (the former is not recommended, because of (2) above).
This is one of the exceptions to that rule. You can choose to use a real DB or an in-memory one - whatever is most convenient. It's common to use docker and tools like that for testing.
In your case, I'd have a specific test-only set of routes that respond to the provider state handler endpoints, that also have access to the repository code and can manipulate state of the system.

How to start a mock server in my ProviderService and call a webservice?

How to create a mock server to call a webservice in my providerservice class.
I created the clientPactTest class with some interactions, created json file, published it, but got stuck at the Verfication part in the ProciderService.
In my scenario i have to call a webservice in my Provider service. Its a typescript project.
Please answer my queries:
1) Right now iam running my webservice at command line at localhost port 8080. Then I created a ProviderService with a Pact mentioning the provider url and hostname as localhost and port 8080. So that all my tests hit the webservice which I started at command line. Is this the right approach?
2) Iam a bit confused as at many websites its mentioned that we dont run the actual service for pacts verification and we should create a mock server. So if I create a mock server, do i have re write all the endpoints in my providerservice file, the way it is mentioned in the actual webservice ?
Please clarify.
Thanks,
Aruna
With provider side verification you always need to run the real provider to ensure it behaves as expected by its consumers. On the consumer side you use the mock service in place of the provider, so perhaps this is where the confusion lies.
In the case where your provider service also is a consumer of another service, the pattern repeats itself.
See https://docs.pact.io/best_practices/provider#only-stub-layers-beneath-where-contents-of-the-request-body-are-extracted and related sections on that page.
The general advice is that you should use local stubs for any downstream service(s) during pact provider testing

Integration testing transaction outputs on the #InitiatedBy side post transaction finality

I have a situation where I have an #InitiatingFlow, called ProposeMemberFlow, and a corresponding #InitiatedBy ProposeMemberFlowResponder. I would like include in my integration test something that tests that the responder has one of the transaction output states post the FinalityFlow sub flow having been kicked off by the initiating flow.
I naively called waitForLedgerCommit in the responding flow, post responding to the CollectSignaturesFlow, but I'm finding that the initiating flow finishes before the responding flow does - presumably the latter is waiting for the vault update.
I'm integration testing through a CordaService - is "the corda way" to use expectEvents to wait for VaultUpdates so that I then know when it's safe to test against the CordaService? Much like here?
Thanks
I haven't heard of integration testing via a CordaService. Generally, you would write integration tests using the node driver.
Here's an example: https://github.com/corda/cordapp-template-kotlin/blob/release-V2/cordapp/src/integrationTest/kotlin/com/template/DriverBasedTest.kt
This piece of code starts a set of nodes, then uses RPC to check some conditions of the node.
In your case, you'd want to use the following set of RPC operations in the node driver:
CordaRPCOps.startFlowDynamic on node A's RPC handle to run the ProposeMemberFlow
CordaRPCOps.vaultQueryBy on node B's RPC handle to check that the correct state has been written to the vault
Another option would be to use the mock network (e.g. https://github.com/corda/cordapp-example/blob/release-V2/kotlin-source/src/test/kotlin/com/example/flow/IOUFlowTests.kt). You could argue that this isn't an integration test, since you are running mock nodes instead of real nodes. However, the mock nodes are just another implementation of the AbstractNode interface, and should behave like normal nodes for the purposes of testing.

Spring Cloud Contract and Spring-WS Endpoints

Can Spring Cloud Contract be used to test Spring Boot services that are running Spring-WS Endpoints? I would like the ability to define SOAP requests/responses using the Groovy DSL, but I haven't been able to get these services to work with Spring Cloud Contract. I keep getting a failure (expected 200 but received a 404) when I try to run these tests. Interestingly, I added #RestController and #RequestMapping annotations to my Endpoint class (knowing it wouldn't work) just to test whether or not the fact that these services are Spring-WS endpoints and not Spring REST controllers may be the problem (i.e., does Spring Cloud Contract only "see" REST endpoints?). And...I moved on to a different set of errors. So, I am assuming at this point that I can not use Spring Cloud Contract to test my SOAP services, but I would like to know for sure (i.e., is there some way to do this that I haven't discovered yet?).
Our core services are implemented as REST services, but we still have to support our SOAP clients until they can migrate to REST, so they wrap our REST services. I need the ability to test both. I have successfully created tests for our REST services.
Try using the explicit mode to make rest assured send real request. In the base class you'll have to setup the whole application so that it bindd to a real port. Then in the before section of your test you need to tell rest assured that I'd should call the following port. And that's it :P

Duplicate REST requests to second endpoint

In order to test how a REST service performs under load I would like to send production data to two service end points, one production service and one test service. I would like the responses from the test service to be ignored so the client has no idea it's request is being sent to 2 services. I would like something in between the client and the service so that I do not need to make any changes to either, just have some sort of additional 'filter' service that the traffic will go through which will then pass the request on untouched but also send a duplicate request to the test service. Someone suggested that I might be able to do this using Apache Camel but it's a bit overwhelming and I don't want to get started learning Camel if my aim is not possible. Has anyone achieved anything similar, either using Camel or some other method?
This can be done by defining a jetty or a cxf endpoint that acts as a proxy routing the request to two other http endpoints ie, the REST services.
from("jetty:http://somehost:8282/xxx").
to("http://prod:8181/rest/service/xyz").
to("http://test:8182/rest/service/xyz");
The client can fire the load to http://somehost:8282/xxx. The client will not be aware that it is being routed to two services.
Note: The test will not yeild a real load result if you are routing the client request to two services via the above route or other proxy/router methodologies. Because some latency will be introduced by the proxy/route itself. Instead i suggest to use some load test tool to generate the load and directly fire to the prod and test endpoints separately.
For example, apache ab benchmark tool. Take a look at this and this.

Resources