简体   繁体   中英

Problems autowiring beans to TestNG test when using spring profiles

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.

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.

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).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM