23

I have wrote following test:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:META-INF/dataContext.xml"},classes = Configiuration.class)
@ActiveProfiles("test")
public class CityDaoImplTest {
....
}

I need to use configuration from xml file and from java class bur when I invoke

mvn test I seee following in console:

Tests in error: 
  initializationError(***.CityDaoImplTest): Cannot process locations AND classes for context configuration [ContextConfigurationAttributes@5bb21b69 declaringClass = '***.CityDaoImplTest', classes = '{***.Configiuration}', locations = '{classpath:META-INF/dataContext.xml}', inheritLocations = true, initializers = '{}', inheritInitializers = true, name = [null], contextLoaderClass = 'org.springframework.test.context.ContextLoader']; configure one or the other, but not both.

How to fix it without rewriting configuration?

gstackoverflow
  • 36,709
  • 117
  • 359
  • 710

2 Answers2

56

From the Spring Docs:

Prior to Spring 3.1, only path-based resource locations were supported. As of Spring 3.1, context loaders may choose to support either path-based or class-based resources. As of Spring 4.0.4, context loaders may choose to support path-based and class-based resources simultaneously.

However, with spring-test there is a small caveat. It uses the SmartContextLoader which is based on AbstractDelegatingSmartContextLoader and unfortunately it is not so smart ;)

@Override
public void processContextConfiguration(
        final ContextConfigurationAttributes configAttributes) {

    Assert.notNull(configAttributes, "configAttributes must not be null");
    Assert.isTrue(!(configAttributes.hasLocations() && configAttributes.hasClasses()), String.format(
        "Cannot process locations AND classes for context "
                + "configuration %s; configure one or the other, but not both.", configAttributes));

As shown in the code, locations and classes can not both be set.

So, how to fix this? Well, one solution is to add an extra config class such as the following:

@Configuration
@ImportResource("classpath:META-INF/dataContext.xml")
class TestConfig {

}

And, in your test code use the following:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {Configuration.class, TestConfig.class})
@ActiveProfiles("test")
public class CityDaoImplTest { ... }

Technically, this is rewriting the configuration but you do not have to alter your existing config, just add a new @Configuration class (and that class can even be in the same file as your test case).

wassgren
  • 18,651
  • 6
  • 63
  • 77
  • 1
    from my pom: 4.0.7.RELEASE – gstackoverflow Jan 16 '15 at 08:26
  • Works also with springBoot 2.7.3/JUnit 5.8.2. Note that the Configuration annotation is not needed in TestConfig since you load it explicitely by your ContextConfiguration annotation – Heri Oct 04 '22 at 12:15
4

Even if is to late for you I will post my answer just to help the other ones which will read this.

Another solution is to declare your Configuration class as bean in dataContext.xml.

All you need to do is:

<bean class="com.packageWhereConfigClassIsPresent.Configuration"/>

Hope it will help someone ;)

Aditzu
  • 696
  • 1
  • 14
  • 25