I have a set of test classes in Quarkus that tests my app classes which use io.quarkus.redis.datasource.RedisDataSource
I want to run @BeforeAll
on each test class to reseed the redis db with known data. The BeforeAll method must be static:
@BeforeAll
static void resetTestData() {
// use a static version of io.quarkus.redis.datasource.RedisDataSource; here
// so I can do something like:
// GraphCommands<String> gc = ds.graph();
// gc.graphQuery(redisdbkey, "CREATE (:XXX {key:'abcd', name:'fred'})");
}
I can’t work out how to make a static instance of io.quarkus.redis.datasource.RedisDataSource;
RedisDataSource ds = new RedisDataSource();
Throws a compiler error "Cannot instantiate the type RedisDataSource"
I tried making a Singleton instance like this:
@Singleton
public class RedisDataSourceSingleton {
private static RedisDataSource instance;
@Inject
public RedisDataSourceSingleton(RedisDataSource ds) {
instance = ds;
}
public static RedisDataSource getInstance() {
if (instance == null) {
throw new IllegalStateException("RedisDataSource is not initialized yet.");
}
return instance;
}
}
but using the singleton like this:
import io.quarkus.redis.datasource.RedisDataSource;
// ...
@BeforeAll
static void resetTestData() {
RedisDataSource ds = RedisDataSourceSingleton.getInstance();
// use ds here
}
throws:
"The method getInstance() from the type RedisDataSourceSingleton refers to the missing type RedisDataSource"
Is there a way to get a static instance of io.quarkus.redis.datasource.RedisDataSource
so I can use its methods in my @BeforeAll
method? I am probably overthinking it!
Thanks,
Murray
2
Answers
Ok. Following Clement's comment above, I have found a way to do what I need using Vert.x
To restate the problem: I have a set of test classes, each with multiple test methods that run in a sequence (think variations on CRUD). I need to reset the FalkorDB graph for each class before the tests in that class run.
The
@BeforeAll
annotation runs before all tests in a class. However, it must be astatic
method and the graph reset must complete before any tests in that class start.A "gotcha" is that the Quarkus (JUnit?) test runner creates a new instance of the class for each test function in that class. That means using the class constructor as a way to initialise the test data is not an option in my case because the result of one test feeds into the next test in that class. The tests use the
@TestMethodOrder(OrderAnnotation.class)
and@Test
@Order(1) ...
annotations to ensure the sequence.My initial plan for BeforeAll was to delete the graph key then run the sequence of Cypher queries to recreate the data. However, doing that in a static way became problematic with the http queue and it is inefficient to be re-running a known set of Cypher queries. More importantly, I realised I could leverage the FalkorDB Graph Copy command to copy a previously created graph in the initial state I needed.
I created a
FalkorGraphSetup
class:So, when the Quarkus app starts I have a class that uses the normal Quarkus Redis Client to create a set of graphs in the FalkorDB, each with the suffix "_is" (initial state). eg
MyGraph1_is
. Nothing special there.Then, in my test class BeforeAll I delete the
MyGraph1
graph and recreate it by copying theMyGraph1_is
graph toMyGraph1
. eg:The maximum test graph has about 50 nodes and edges. I have about 20 test classes. At this scale it all works really well. I haven't tried it with giant graphs yet.
Any suggestions for improvement would be very welcome.
Ultimately, I am heading towards building a responsive Quarkus FalkorDB client using Vert.x modelled on the existing Quarkus Redis client but incorporating just the FalkorDB commands.
Cheers, Murray
You cannot access a managed bean (like your data source) from a @BeforeAll.
I would use
@Before
instead or a customQuarkusTestResourceLifecycleManager,
which would run before all tests.Another solution, if you need a @BeforeAll, is to instantiate a low-level Redis client (like the Vert.x Redis client used in Quarkus) and execute the commands.