If I add too many test classes, I get OOM errors. Memory snapshots at the critical moments contain many DefaultListableBeanFactory instances. The amount of DefaultListableBeanFactory instances grow up after adding new test classes. I have Testcontainers for using a PostgreSQL container. I disable unnecessary components with a test application configuration. Any suggestions? Thanks
#Spring Boot, JUnit Jupiter, Testcontainers, OOM
52 messages · Page 1 of 1 (latest)
⌛ This post has been reserved for your question.
Hey @cosmic fiber! Please use
/closeor theClose Postbutton above when you're finished. Please remember to follow the help guidelines. This post will be automatically closed after 300 minutes of inactivity.
TIP: Narrow down your issue to simple and precise questions to maximize the chance that others will reply in here.
Are you stopping the containers after each test?
I use the @Container annotation with the static DB container's field. And I use the @DirtiesContext annotation. So a DB container is controlled automatically.
Can you check whether it is actually stopped automatically on each test?
I use the static field, so a container is closed automatically after all the methods in a test class. I had checked it. Tests run sequentially
seems like there's an infinite loop of spring contexts starting?
There's the finite amount of spring context every time 🙂 When I had less tests, it worked well. The spring.test.context.cache.maxSize property doesn't change my situation
Can you show the @DirtiesContext tests?
or one of them
I mean, I know there are bugs related to @DirtiesContext but I don't know of any like that
I use this hierarchy:
@Testcontainers
@DirtiesContext
@ActiveProfiles("test-containers")
public abstract class PostgresContainerBaseTest {
@Container
public static final PostgreSQLContainer<?> postgresDB = new PostgreSQLContainer<>
("postgres:13.2")
.withDatabaseName("")
.withUsername("")
.withPassword("");
@DynamicPropertySource
public static void properties(DynamicPropertyRegistry registry) {}
}
@SpringJUnitConfig
@SpringBootTest(...)
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
@Transactional
public abstract class ApplicationContainerBaseTest extends PostgresContainerBaseTest {}
@AutoConfigureMockMvc
class PropertyValueMockMvcTest extends ApplicationContainerBaseTest {
@Autowired
private MockMvc mockMvc;
@Test
void getPropertyValueSuccessfullyTest() {}
}
Please format your code to make it more readable.
For java, it should look like this:
````java
public void foo() {
}
````
I don't know about @Container - wouldn't you normally use @ClassRule?
Also is the @DirtiesContext really necessary?
Also, what JUnit version are you using?
@ClassRule is not for JUnit Jupiter. It is for JUnit 4. Isn't it?
@ClassRule is for JUnit 5 I think
well maybe not
try not putting the container in a superclass
try putting it in the subclasses
Yeah, it's useful because I have many test methods in each test class
And do these tests mess up the context?
like are they changing fields in components or similar?
it's 5.8.2
I use the @SpringJUnitConfig. It includes SpringExtension for JUnit Jupiter. I had googled that I don't need @ClassRule because of it
I understand. I will try
Yeah, some of them do
then only use @DirtiesContext on the tests that do?
and what exactly goes OOM? The JVM running the tests?
What do you mean? I don't understand. Some test methods change DB state, for example. On the other hand, I need to run one DB container for all the test classes and prepare the DB manually. It looks ugly
Spring should normally reset the DB between tests
in most cases
Using @DirtiesContext only with special test classes. I will check it also
Other system threads show it. Right. Here are some examples:
Exception: java.lang.OutOfMemoryError thrown from the UncaughtExceptionHandler in thread "logback-53"
Exception in thread "Catalina-utility-2" java.lang.OutOfMemoryError: Java heap space
Exception in thread "RMI TCP Connection(idle)" java.lang.OutOfMemoryError: Java heap space
I will check it
Now I have 3 ways for the further investigation
ok so the main application goes OOM
Can you check the memory usage over time? Does it slowly accumulate?
Also, can you get a heapdump and analyze it?
Yes, I can. I use the profiler by Jetbrains. The memory usage grow up slowly, right. And it looks like a saw
Yeah, I can capture the heap with the profiler
ideally do the heap dump right before the OOM
or configure it to automatically do a heapdump when the OOM occurs
Right. I can do that. I had tried to do that. I had seen many allocations by DefaultListableBeanFactory. What can we do with that? I can post a screenshot
Here's a screenshot
maybe check where it is referenced from
maybe you have a static field storing your contexts somewhere
Right! I will try
Now I have 5 ways for the further investigation
💤 Post marked as dormant
This post has been inactive for over 300 minutes, thus, it has been archived.
If your question was not answered yet, feel free to re-open this post or create a new one.
After many hours, I increased the maximum heap memory. It was enough because the application became more heavy. Thank you, Daniel!
If you are finished with your post, please close it.
If you are not, please ignore this message.
Note that you will not be able to send further messages here after this post have been closed but you will be able to create new posts.