7

I created a meta annotation @EmbeddedMongoDBUnitTest that activates two profiles to be used in spring based unit tests. The basic setup works:

@Documented
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@ActiveProfiles({"embeddedMongoDB", "embeddedMongoDBUnitTest"})
public @interface EmbeddedMongoDBUnitTest {
}

@RunWith(SpringJUnit4ClassRunner.class)
@EmbeddedMongoDBUnitTest
@ContextConfiguration(...)
public class WorkingTest {
    ...
}

Now when trying to activate another profile with another @ActiveProfiles annotation on the test class itself, the profiles in @EmbeddedMongoDBUnitTest aren't activated anymore:

@RunWith(SpringJUnit4ClassRunner.class)
@EmbeddedMongoDBUnitTest
@ActiveProfiles({"h2IntegrationTests"})
@ContextConfiguration(...)
public class NotWorkingTest {
    ...
}

Is there a reason why this is not working or is this a bug in the spring test code?

James
  • 11,654
  • 6
  • 52
  • 81

1 Answers1

11

This is not a bug: this is by design.

The reason this does not work is that this form of configuration is simply not supported by Spring.

The algorithm that the Spring Framework uses when searching for an annotation stops once it has found the first occurrence of the sought annotation. Thus, in your example, the @ActiveProfiles annotation on NotWorkingTest effectively shadows the @ActiveProfiles annotation on your composed @EmbeddedMongoDBUnitTest annotation.

Please note that these are the general semantics for annotations in the core Spring Framework. In other words, the behavior you are experiencing is not specific to the spring-test module.

Having said that, profiles declared via @ActiveProfiles are in fact inherited within a test class hierarchy (unless you set the inheritProfiles flag to false). But don't confuse class hierarchies with annotation hierarchies: Java supports inheritance for interfaces and classes but not for annotations.

Hope this clarifies things!

Sam (component lead for the spring-test module)

Sam Brannen
  • 29,611
  • 5
  • 104
  • 136
  • Thanks for the exploration Sam. If this is not a bug, I'm questioning the design here. It may be true that the spring framework only searches for the first Annotation, but in this case one really expects that all @ActiveProfiles annotations are picked up, esp. if it's supported with class inheritance. – James Oct 13 '14 at 14:27
  • James, feel free to create a JIRA issue to request such a feature at http://jira.spring.io, and we will consider it. – Sam Brannen Oct 13 '14 at 17:59
  • @SamBrannen Is there any JIRA ticket regarding this issue? I didn't manage to find it yet – Anton Jul 01 '16 at 14:21
  • It could be a good time to say that since Spring 4 this has changed and @ActiveProfiles is a meta-annotation – usr-local-ΕΨΗΕΛΩΝ Mar 21 '18 at 15:39
  • `@ActiveProfiles` is not a meta-annotation per se. It's an annotation which _can_ be used as a meta-annotation since Spring 4. However, the OP was obviously already using Spring 4+, since his `@EmbeddedMongoDBUnitTest` worked stand-alone. – Sam Brannen Mar 21 '18 at 15:50
  • @Anton, I don't think anybody ever created a JIRA issue for this topic. – Sam Brannen Mar 21 '18 at 15:55
  • I opened an issue: https://github.com/spring-projects/spring-framework/issues/23299 – Gebezs Jul 16 '19 at 16:32
  • The upcomming Spring Framework 5.2 will include this: https://github.com/spring-projects/spring-framework/issues/23299#issuecomment-515765514 – Gebezs Aug 05 '19 at 14:35
  • Issue for composable `@ActiveProfiles` is https://github.com/spring-projects/spring-framework/issues/26145 – drekbour Mar 02 '22 at 17:27