1

I am currently polishing a test framework we have. For the current needs, we must support multiple spring profiles, and run our tests multiple times, each time with a different profile. Each profile targets separate test environments, and thus different sets of tests, with different logic may be executed.

I am having a test class like this:

@ContextConfiguration(locations = { "classpath:META-INF/test-context.xml" })
public class Test extends AbstractTestNGSpringContextTests {
    @Autowired
    ProfileSpeciticBean profileSpecificBean;

    ...
}

Here, ProfileSpecificBean is an interface, that is implemented by separate classes. The actual implementation to be injected is determined by the active Spring profile, and I am using Spring XML contexts. I am building the project with Maven, using the -Dspring.profiles.active=profileName command, thus expecting the tests to catch the passed profile.

However, the current test fails with this error within the full stacktrace:

org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type ProfileSpeciticBean found for dependency: expected at least 1 bean which qualifies as autowire candindate, found 0

After some reaearch on this topic, I found that the AbstractTestNGSpringContextTests expects an @ActiveProfiles annotation on top of the test class. So, this code works:

 @ContextConfiguration(locations = { "classpath:META-INF/test-context.xml" })
 @ActiveProfiles("profile1")
 public class Test extends AbstractTestNGSpringContextTests ...

The problem with this is: I want to avoid hard-coding the profile name in my classes. I need to run the same test class for different profiles, by only altering the command-line script.

Is the above possible? Is there any way to make TestNG aware of the command-line profile, and re-use the same test? I need to avoid both duplicating code and configuration to make my tests run, so making two Test classes for each profile is not what I want.

titusn
  • 1,201
  • 1
  • 12
  • 43
Ivaylo Slavov
  • 8,839
  • 12
  • 65
  • 108

2 Answers2

1

To get more precise answer I suggest you add stacktrace and the piece of you main configuration (where you declared beans that is supposed to be replaced by test beans).

Here is the general idea:

let's say you want to change PropertyPlaceholderConfigurer depending on your profile.

Steps:

  1. You create you main-config.xml that contains PropertyPlaceholderConfigurer and mark it with profile="default"
  2. You create you test-config.xml with test implementation of PropertyPlaceholderConfigurer
    (don't forget to mark test-config.xml with profile="MyTestProfile" or mark only PropertyPlaceholderConfigurer with profile="MyTestProfile)
  3. Than you import both test-config.xml and main-config.xml to your tests

 

 @ContextConfiguration(locations = { "classpath:META-INF/main-config.xml","classpath:META-INF/test-config.xml" })
 @ActiveProfiles("MyTestProfile")
 public class Test extends AbstractTestNGSpringContextTests {}

It should work. Good luck.

Ivaylo Slavov
  • 8,839
  • 12
  • 65
  • 108
Yurii Bondarenko
  • 3,460
  • 6
  • 28
  • 47
  • Thank you for your answer. Actually, I want to remove the `@ActiveProfiles("MyTestProfile")` part. I want to be able to run the same `Test` class with `profile1` and `profile2`, depending on the command-line. Thus, I must avoid hard-coding the profile name in my class. I have already made this work with the `@ActiveProfiles` annotation – Ivaylo Slavov Aug 04 '14 at 09:16
1

Try following How to set JVM parameters for Junit Unit Tests? to set the system variables for the VM that actually runs the tests - it's not the same one as the one that runs maven.

Set your profile there.

You can use a maven system parameter to set that from the invocation of maven (or use maven profiles).

Community
  • 1
  • 1
Michael Wiles
  • 20,902
  • 18
  • 71
  • 101
  • Thanks @Michael, your link lead me to the solution. In particular, I had to change my surefire plugin configuration to include this line: `-Dspring.profiles.active=${spring.profiles.active}` into the `configuration` section, as pointed by [this answer](http://stackoverflow.com/a/7579853/795158) for the thread you've linked. In my settings, `${spring.profiles.active}` is a property defined by my maven build profile, representing the associated with it spring profile. – Ivaylo Slavov Aug 04 '14 at 10:45
  • 1
    I would have linked the answer if I'd known how at the time - Now I know how :-P – Michael Wiles Aug 04 '14 at 11:20