简体   繁体   中英

TestExecutionListeners annotation prevents spring beans being wired in

Following the cassandra-unit with spring example I found the spring beans are not wired into the testclass resulting in nullpointer exceptions. I tried to minimise the problem and found it is probably not the Cassandra part, but instead the presence of a @TestExecutionListeners annotation, together with a AbstractTestExecutionListener extended class.

org.springframework:spring-core:4.2.0.RELEASE (Also fails with 3.2.14.RELEASE).
org.springframework:spring-test:4.2.0.RELEASE
junit.junit:4.11

JVM vendor/version: Java HotSpot(TM) 64-Bit Server VM/1.8.0_40
MAC OS X 10.10.5

my TestClass looks like:

@RunWith(SpringJUnit4ClassRunner.class)
@TestExecutionListeners({ AppTestListener.class }) <-- OK when removed
@ContextConfiguration(classes = { TestConfiguration.class })

public class MyTest {
  @Autowired
  private MyService myService;

  @Test
  public void testMyService() {
    Assert.assertNotNull(myService);
    Assert.assertEquals("didit", myService.doIt());
  }
}

AppTestListener:

public class AppTestListener extends AbstractTestExecutionListener {
  @Override
  public void beforeTestMethod(TestContext testContext) throws Exception {
    System.out.println("test");
  }
}

Nothing special in the configuration class (and it also fails for configuration xml):

@Configuration
public class TestConfiguration {
  @Bean
  public MyService myService() {
    return new MyService(); 
  }
}

When I remove the @TestExecutionListeners annotation in MyTest the test finishes as expected, but leaving that annotation makes the unittest fail on the assertNotNull. What is happening?

For starters, the cassandra-unit example is unfortunately not really a good example since it leads to issues just like you encountered.

When I remove the @TestExecutionListeners annotation in MyTest the test finishes as expected, but leaving that annotation makes the unittest fail on the assertNotNull. What is happening?

When you declare @TestExecutionListeners(AppTestListener.class) on a test class that does not extend any other test class annotated with @TestExecutionListeners you are effectively telling Spring to load only your AppTestListener , when you actually want to use AppTestListener in combination with the default listeners from Spring (eg, the DependencyInjectionTestExecutionListener which adds support for dependency injection of beans from the ApplicationContext ).

For details, please read the entire TestExecutionListener configuration section of the Spring reference manual.

Here's how to fix your problem.

Before Spring Framework 4.1

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
@TestExecutionListeners({
  CassandraUnitTestExecutionListener.class,
  DependencyInjectionTestExecutionListener.class,
  DirtiesContextTestExecutionListener.class,
  TransactionalTestExecutionListener.class
})
@CassandraUnit
public class MyCassandraUnitTest {

  @Test
  public void xxx_xxx() {
  }
}

After Spring Framework 4.1

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
@TestExecutionListeners(
  listeners = CassandraUnitTestExecutionListener.class,
  mergeMode = MERGE_WITH_DEFAULTS
)
@CassandraUnit
public class MyCassandraUnitTest {

  @Test
  public void xxx_xxx() {
  }
}

Regards,

Sam ( author of the Spring TestContext Framework )

ps I created an issue for Cassandra Unit so that they address this in their examples.

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