Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 377
dr jerry Avatar asked Aug 29 '15 13:08

dr jerry


People also ask

Which of the following annotation is supported by spring for unit testing JPA components?

@JdbcTest: We can use the @JdbcTest annotation to test JPA applications, but it's for tests that only require a DataSource. The annotation configures an in-memory embedded database and a JdbcTemplate.

Which annotation is used for testing Spring MVC which apply only the configuration related to MVC?

Again, very similar to the @DataJpaTest and the @DataMongoTest annotations, to perform classic Spring MVC tests, we apply the @WebMvcTest annotation alongside the @RunWith(SpringRunner. class) annotation. Keep in mind that the effects of this annotation only apply to the MVC infrastructure.

What is SpringJUnitConfig?

@SpringJUnitConfig is a composed annotation that combines @ExtendWith(SpringExtension. class) from JUnit Jupiter with @ContextConfiguration from the Spring TestContext Framework. As of Spring Framework 5.3, this annotation will effectively be inherited from an enclosing test class by default.

What is context configuration in spring?

@ContextConfiguration defines class-level metadata that is used to determine how to load and configure an ApplicationContext for integration tests.


1 Answers

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 (e.g., 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)

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

like image 179
Sam Brannen Avatar answered Nov 15 '22 20:11

Sam Brannen