micronaut-projects / micronaut-test-resources

Test resources support
Apache License 2.0
8 stars 17 forks source link

Two datasources reuse the same mysql container #371

Open JesusMetapack opened 1 year ago

JesusMetapack commented 1 year ago

Feature description

Using Micronaut 3.9.x

We have this configuration

test-resources:
  containers:
    mysql:
      image-name: mysql:8
      db-name: cost-engine
      username: cost-engine
      password: test # According to test containers documentation this is used as the password for the root user also

datasources: # URL will be inserted by Micronaut test resources
  read:
    db-type: mysql
  write:
    db-type: mysql

The test resource resolver injects the properties url, username and password correctly to both datasources, but our repository classes should be able to use the read and the write datasource pointing to the same container The reason is that in real life, our mysql database has two urls, one for reads and one for writes, but they both use the same physical database

Unfortunately I cant find a way for micronaut to do that, and just spin one container for both datasources Ultimately the function that is exectuted to decide about a new container is:

io.micronaut.testresources.testcontainers.TestContainers.getOrCreate(...)

And the logic is more or less like this:

       ....
        Key key = Key.of(owner, name, Scope.from(query), query);

        T container = (T) CONTAINERS_BY_KEY.get(key);
        if (container == null) {
            ...
            container.start();
            CONTAINERS_BY_KEY.put(key, container)

the CONTAINERS_BY_KEY map is used to detect if it needs to inject a new container to resolve a resource The key is based on a criteria which makes datasources.read.* and datasources.write.* two different keys.

Would be good to be able to tell the resolver, that we want both datasources to just use the same container url, etc.., but i cannot see that happening given the current resolution logic

Is there a way to achieve this currently, just via configuration?

JesusMetapack commented 1 year ago

Maybe a solution would be to add a property called db-name to a datasource, so it could identify the container

test-resources:
  containers:
    mysql:
      image-name: mysql:8
      db-name: cost-engine
      username: cost-engine
      password: test # According to test containers documentation this is used as the password for the root user also

datasources: # URL will be inserted by micronaut test resources
  read:
    db-type: mysql
    db-name: cost-engine
    dialect: MYSQL
    username: cost-engine
    password: test
  write:
    db-type: mysql
    db-name: cost-engine
    dialect: MYSQL
    username: cost-engine
    password: test
melix commented 1 year ago

The behavior you're describing is indeed intentional and the result of design decisions, so that it works in more cases than just databases. I'm going to think about how we could explicitly tell which test resource to use (intentionally not saying the term container) so that it works in a generic way.

svrdoljak commented 4 months ago

@melix is there any progress on this? We have multiple datasources and I want to spin up 3 containers with test-resources and define which datasource should use which test-resource. We are on MN4 right now. Thanks!