I have a Spring Boot REST API application that uses different profiles like dev, test, prod, etc
It also makes a call to another API to retrieve some data like:
Client ---> MYAPI ---> DOWNSTREAMAPI
MyAPI is working fine and it will get data from DOWNSTREAMAPI and return it to client.
However, for client e2e testing purposes, I would like to be able to return it an isolated set of data so when client calls MYAPI, it will always get this set of data.
So, this is different from unit testing or integration testing of MYAPI. This is to build MYAPI so it gets real data from DOWNSTREAMAPI if active profile is set to "prod" and to get mocked data if active profile is "dev" so when client calls MYAPI running in "dev" mode, this mocked data will be returned to it. This will ensure that client e2d tests will always operate on isolated test data that does not change.
This data is not coming from a database but from another API.
I was not able to find a suggestion how to design this. All I was finding is how to mock services from within unit tests or integration tests but this is not what I am doing here.
So, I came up with my own solution which looks like below
Controller
My controller calls HelloService which has different implementation based on currently set active profile
@RestController
@RequestMapping("/testdatamocking")
public class HelloController {
@Autowired
private HelloService helloService;
@GetMapping("/hello")
public String hello() {
return helloService.hello();
}
}
Services
HelloService interface:
public interface HelloService {
String hello();
}
HelloService implementations:
@Service
@Profile("!dev")
public class RealHelloServiceImpl implements HelloService{
@Override
public String hello() {
return "real hello";
}
}
@Service
@Profile("dev")
public class MockHelloServiceImpl implements HelloService {
@Override
public String hello() {
return "mocked hello";
}
}
I have different application properties files:
- application.properties
- application-prod.properties
- application-dev.properties
- application-test.properties
The HelloService
implementations are annotated with @Profile
which determines which implementation will be created in spring context based on the currently used spring active profile in application.properties.
If my application.properties sets spring.profiles.active=dev
, then MockHelloServiceImpl
will be created.
Otherwise, is my application.properties set spring.profiles.active
to some other profile, then RealHelloServiceImpl
will be created.
UPDATE
I would like to expand on this so that I can return different data based on the provided request body. This is because this will be used in Cucumber/Cypress e2e tests on client side.
A client could send a POST request with body like:
{"id":2, "type":1}
For this POST request, response could contain a JSON body containing data for item with id=2 and of type=1.
As the id
and type
can change in this request, different data would need to be returned. As this is data for testing purposes, I want to make it non-volatile in order to produce consistent tests, but I am not sure what would be a good way and how to create this non-volatile data to be returned.
Would it be just hardcoded list of items which can be modified to add new items for new test cases?
Or an in-memory H2 database containing the items or something else?