Skip to content

Annotating an integration test with @IfProfileValue at class level still loads the applications contexts even when the profile is not activated [SPR-5043] #9718

@spring-projects-issues

Description

@spring-projects-issues

Lars Bo Mortensen Spring opened SPR-5043 and commented

When annotating a integration type unit test using the excellent @IfProfileValue annotation set at class level, the application contexts defined in @ContextConfiguration are still loaded and dependency injection is done in the test, even though no test methods are executed.

This can be rather time consuming as the integration tests excercise more heavy weight services than is otherwise the case with normal unit tests.

The following unit test highlights the problem:

import static junit.framework.Assert.assertNotNull;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.annotation.IfProfileValue;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "/nonExistingAppCtx.xml" })
@IfProfileValue(name = "test-group", value = "integration")
public class IntegrationTest {

	@Autowired
	String myNonExistingApplicationContextBean;

	@Test
	public void test() {
		assertNotNull(myNonExistingApplicationContextBean);
	}
}

The test class should only be run if the test-group system property is set. The expected behaviour when running the test should IMHO be that to report that the testclass contained 1 ignored test. If the test class is run with the test-group property set, it should throw exceptions as the context configuration does not point to a valid application context.

When running the code with Spring 2.5.5 without setting the test-group property, an exception is instead thrown as the the app context is still attempted loaded and dependency injection is attempted.

This is due to the behaviour of createTest in SpringJUnit4ClassRunner which does not check if the testclass should be run at all:

/**
 * Delegates to {@link JUnit4ClassRunner#createTest()} to create the test
 * instance and then to a {@link TestContextManager} to
 * {@link TestContextManager#prepareTestInstance(Object) prepare} the test
 * instance for Spring testing functionality.
 * @see JUnit4ClassRunner#createTest()
 * @see TestContextManager#prepareTestInstance(Object)
 */
@Override
protected Object createTest() throws Exception {
	Object testInstance = super.createTest();
	getTestContextManager().prepareTestInstance(testInstance);
	return testInstance;
}

The call to prepareTestInstance causes all the test execution listeners to fire, and inject the dependencies. By making a simple guard check to see if any methods should be processed at all, the problem can be eliminated. Alternatively it could be part of the TestContextManager's responsibility.

I hope that my explanation is complete enough to give you an understanding of the issue.


Affects: 2.5.5

Attachments:

Issue Links:

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions