Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reconsider default for spring.datasource.generate-unique-name as the current one makes test cases brittle #16747

Closed
odrotbohm opened this issue May 8, 2019 · 9 comments
Assignees
Labels
type: enhancement A general enhancement
Milestone

Comments

@odrotbohm
Copy link
Member

odrotbohm commented May 8, 2019

Issue

The current default for spring.datasource.generate-unique-name (false) causes issues in combination with the default used for Hibernates DDL setting spring.jpa.generate-ddl (create-drop) in the context of Spring Test's context caching. I've attached a sample project that shows the issue.

Steps to reproduce

  1. Unzip the linked file
  2. Run mvn clean test
  3. See the third test case fail as it cannot find data inserted during bootstrap of the context for the first test case.

Context

Here is what's going on:

  1. We have two different context bootstraps. One that's inserting a bit of commonly shared data the application needs. The other one is not including that component. This is just a dummy setup for test cases that use a diverse set of configurations and include components that manipulate the database.
  2. When the first test bootstraps, an embedded database instance is created, the schema is created and the component sets up the data in the database.
  3. When the second test bootstraps, the default of create-drop causes the database schema being wiped and recreated. As this context does not contain the component setting up the reference data, the database remains initialized but unpopulated. This is fine for this particular context. However, as the database is shared across the application contexts, the other cached one is affected, too.
  4. The third test case uses the same context as the first one but now doesn't find the data wiped by the second one anymore.

Underlying problems

There are a couple of problematic aspects about the current setup:

  • A bean definition in an application creating a resource that's shared across application contexts is unexpected as that's not the way it works for any other bean.
  • Whether the behavior imposes a problem is dependent on the order of the test classes during JUnit execution. If the third test is executed before the second one the problem disappears. This makes diagnosing the problem even harder.

Workarounds

  • Explicitly setting spring.datasource.generate-unique-name=true causes database instances to be created per ApplicationContext.

Proposed solution

  • Change the default of spring.datasource.generate-unique-name to true.

Side-effects of the solution

  • In an internal discussion, @wilkinsona mentioned that a flip in the default would probably cause issues in DevTools, as it is re-bootstrapping the ApplicationContext and – with the new default – would lose the data entered while using the application. This could be mitigated by letting DevTools explicitly disable the property by default.

Further references

AFAIK, @sbrannen had a few thoughts on that as well.

@sbrannen
Copy link
Member

AFAIK, @sbrannen had a few thoughts on that as well.

Yes, I always advocate generating a random database name for embedded databases in Spring integration tests.

Over the years I have seen numerous projects that ran into issues with @DirtiesContext as well as the LRU eviction policy for the ContextCache, and the only viable solution was using a random database name.

In fact, I updated the Spring Framework reference manual quite awhile ago (several years?) to point that out.

In summary, if it's feasible I think it would be beneficial if spring.datasource.generate-unique-name=true was the default in Spring Boot for integration tests.

@wilkinsona wilkinsona added the for: team-attention An issue we'd like other members of the team to review label May 10, 2019
@philwebb philwebb self-assigned this May 10, 2019
@philwebb
Copy link
Member

Digging though the code a bit we think this might be a safe change to make but we'll need some time to experiment to make sure there are no unexpected side effects.

@philwebb philwebb removed the for: team-attention An issue we'd like other members of the team to review label May 10, 2019
@wilkinsona
Copy link
Member

See #4699 for the DevTools side of things.

@odrotbohm
Copy link
Member Author

Can we bring this on the table for 2.3 again?

@philwebb philwebb added the for: team-attention An issue we'd like other members of the team to review label Oct 28, 2019
@philwebb philwebb added this to the 2.3.x milestone Nov 6, 2019
@philwebb philwebb added type: enhancement A general enhancement and removed for: team-attention An issue we'd like other members of the team to review status: waiting-for-triage An issue we've not yet triaged labels Nov 6, 2019
@philwebb
Copy link
Member

philwebb commented Nov 6, 2019

@odrotbohm Yeah, we'll try again to get this into the next version

@nightswimmings
Copy link

@wilkinsona @philwebb But given the context caching and reuse, isn't this gonna open several db instances in memory?

@wilkinsona
Copy link
Member

Yes, and that is intentional and desirable as explained above by @odrotbohm and @sbrannen.

@OrangeDog
Copy link
Contributor

This has the side-effect that name now does nothing unless generate-unique-name is also overridden to false.

I would expect setting the name to set the name, with no other properties set.

@wilkinsona
Copy link
Member

I'm not sure why you have that expectation. The name property's documentation states that it is the "Datasource name to use if generate-unique-name is false".

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: enhancement A general enhancement
Projects
None yet
Development

No branches or pull requests

8 participants