Assume the following component:
@Component
public class MyComponent {
private static MyComponent INSTANCE = new MyComponent();
private MyComponent() {
INSTANCE = this;
}
public static MyComponent getInstance() {
return INSTANCE;
}
}
And in another class I have this Helper component class:
@Component
public class MyBeanHelper {
private static MyBeanHelper INSTANCE = new MyBeanHelper();
private MyBeanHelper() {
INSTANCE = this;
}
public static MyBeanHelper getInstance() {
return INSTANCE;
}
@Autowired
private MyComponent component;
public MyComponent getComponent () {
return component;
}
}
Now. I have the following tests:
@ActiveProfiles("myProfile1")
public class TestA extends MyIntegrationAbstractTest {
@Test
public void test() {
System.out.println("===============1: "+ MyBeanHelper.getInstance().getComponent().toString());
}
}
and
@ActiveProfiles({"myProfile1", "myProfile2"})
public class TestB extends MyIntegrationAbstractTest {
@Autowired
private MyComponent component;
@Test
public void test() {
System.out.println("===============2: "+ component.toString());
}
}
and
@ActiveProfiles("myProfile1")
public class TestC extends MyIntegrationAbstractTest {
@Test
public void test() {
System.out.println("===============1: "+ MyBeanHelper.getInstance().getComponent().toString());
}
}
Where MyIntegrationAbstractTest specified the SpringTestRunner and ComponentScans
The following behaviour was noticed in spring:
- Spring Context is Created for TestA
- Spring Context is re-created for TestB
- Test C has the same profiles as Test A, so we re-use a cached version of the context created in Step 1.
The issue is that in step 2, When it creates the component, it is setting the static INSTANCE variable as well. However, as this is static, it is in fact the same variable present in the Context of step 1, hence overriding it. When TestC comes to execute, the context will be mostly the context of TestA, but with any static instances still from TestB.
In fact possible output:
===============1: MyComponent@680bddf5
===============2: MyComponent@2caf6912
===============3: MyComponent@2caf6912
If you add a @DirtiesContext on TestA the cached context will be destroyed and a new Context will be created for TestC. However this requires knowledge of tests outside the actual test which goes against core testing principles. The alternative would be to set @DirtiesContext on all the tests which would prevent this problem but be a severe hit in performance as all the test classes would require the context to be rebuilt.
Are there any possible other solutions to this messy problem?
Aucun commentaire:
Enregistrer un commentaire