Java 如何使用不同的JUnit Runner运行Spring单元测试?
我正在用多线程测试一个事件处理器。因此,我在测试用例中使用vmlens的并发junit。 但我在自动连接bean时遇到了null点异常,因为我使用的是ConcurrentTestRunner而不是SpringJunit4ClassRunner。 这是我的pomJava 如何使用不同的JUnit Runner运行Spring单元测试?,java,multithreading,junit,Java,Multithreading,Junit,我正在用多线程测试一个事件处理器。因此,我在测试用例中使用vmlens的并发junit。 但我在自动连接bean时遇到了null点异常,因为我使用的是ConcurrentTestRunner而不是SpringJunit4ClassRunner。 这是我的pom <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.vmlens</groupId>
<artifactId>concurrent-junit</artifactId>
<version>1.0.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<version>2.6.0</version>
<scope>test</scope>
</dependency>
显然,豆子没有正确注射。
有办法解决这个问题吗?我应该扩展AbstractJUnit4SpringContextTests吗
此处附上最新代码: EventStore是一个Jpa存储库:
public interface EventStore extends JpaRepository<DomainEvent, Long>{};
测试用例:
import com.anarsoft.vmlens.concurrent.junit.ConcurrentTestRunner;
import com.anarsoft.vmlens.concurrent.junit.ThreadCount;
@RunWith(ConcurrentTestRunner.class)
@ContextConfiguration(locations = "classpath:applicationContext.xml")
public class EventListenerTest {
@ClassRule
public static final SpringClassRule springClassRule = new SpringClassRule();
@Rule
public final SpringMethodRule springMethodRule = new SpringMethodRule();
@Autowired
private EventStore es;
@Autowired
private EntityAppender ea;
......
@Before
public void setUp() throws Exception {
bef = es.count(); //<====nullpoint exception due to es being null here
}
@Test
@ThreadCount(10)
public final void testDefaultListener() {
bef = es.count(); //<====== es worked well here
TestEntity1 t1 = ea.appWithDefaultListener();
......
}
}
import com.anarsoft.vmlens.concurrent.junit.ConcurrentTestRunner;
导入com.anarsoft.vmlens.concurrent.junit.ThreadCount;
@RunWith(ConcurrentTestRunner.class)
@ContextConfiguration(locations=“classpath:applicationContext.xml”)
公共类EventListenerTest{
@阶级规则
公共静态最终SpringClassRule SpringClassRule=新SpringClassRule();
@统治
公共最终SpringMethodRule SpringMethodRule=新的SpringMethodRule();
@自动连线
私人活动;
@自动连线
私人实体附录ea;
......
@以前
public void setUp()引发异常{
bef=es.count();//自Spring 4.2以来,当您出于其他原因(例如ConcurrentTestRunner
或Mockito的MockitoJUnitRunner
)需要提供自己的JUnitRunner
时,Spring提供了一种单独的机制来初始化单元测试的ApplicationContext
和元配置
这个机制是两个JUnit4规则的组合。这在官方文档中有记录
org.springframework.test.context.junit4.rules
包提供
遵循JUnit4规则(JUnit4.12或更高版本支持)
SpringClassRule
SpringMethodRule
SpringClassRule
是支持类级功能的JUnitTestRule
SpringTestContext框架;然而,SpringMethodRule
是
JUnitMethodRule
支持实例级和方法级
SpringTestContext框架的特性
单元测试类应至少包含
@ClassRule
public static final SpringClassRule SPRING_CLASS_RULE = new SpringClassRule();
@Rule
public final SpringMethodRule springMethodRule = new SpringMethodRule();
下面是一个完整的示例,它利用了MockitoJUnitRunner
,同时仍然使用Spring的TestContext框架:
@ContextConfiguration(classes = ConfigExample.class)
@RunWith(MockitoJUnitRunner.class)
public class Example {
@ClassRule
public static final SpringClassRule SPRING_CLASS_RULE = new SpringClassRule();
@Rule
public final SpringMethodRule springMethodRule = new SpringMethodRule();
@Autowired
private Foo foo;
@Mock
private Runnable runnable;
@Test
public void method2() {
Mockito.doNothing().when(runnable).run();
foo.bar(runnable);
Mockito.verify(runnable).run();
}
}
@Configuration
class ConfigExample {
@Bean
public Foo Foo() {
return new Foo();
}
}
class Foo {
public void bar(Runnable invoke) {
invoke.run();
}
}
查看建议的
@ClassRule
和@Rule
解决方案,这避免了使用Spring的SpringJUnit4ClassRunner
@SotiriosDelimanolis我也找到了相同的解决方案,谢谢。@SotiriosDelimanolis出现了另一个问题。当我在“@Before”中使用自动连线时方法,它给了我一个空点。Spring上下文似乎在“@Test”之前注入了组件方法。您必须提供一个示例。注入发生后应调用@Before
方法。不幸的是,我无法重现您看到的行为。您可以在此处或在新问题中提供一个示例吗?正如我之前所评论的,我跟踪了引导过程,发现注入发生在“@Test”方法,但在“@Before”方法之后。我在问题中附上了上面的代码。
import com.anarsoft.vmlens.concurrent.junit.ConcurrentTestRunner;
import com.anarsoft.vmlens.concurrent.junit.ThreadCount;
@RunWith(ConcurrentTestRunner.class)
@ContextConfiguration(locations = "classpath:applicationContext.xml")
public class EventListenerTest {
@ClassRule
public static final SpringClassRule springClassRule = new SpringClassRule();
@Rule
public final SpringMethodRule springMethodRule = new SpringMethodRule();
@Autowired
private EventStore es;
@Autowired
private EntityAppender ea;
......
@Before
public void setUp() throws Exception {
bef = es.count(); //<====nullpoint exception due to es being null here
}
@Test
@ThreadCount(10)
public final void testDefaultListener() {
bef = es.count(); //<====== es worked well here
TestEntity1 t1 = ea.appWithDefaultListener();
......
}
}
@ClassRule
public static final SpringClassRule SPRING_CLASS_RULE = new SpringClassRule();
@Rule
public final SpringMethodRule springMethodRule = new SpringMethodRule();
@ContextConfiguration(classes = ConfigExample.class)
@RunWith(MockitoJUnitRunner.class)
public class Example {
@ClassRule
public static final SpringClassRule SPRING_CLASS_RULE = new SpringClassRule();
@Rule
public final SpringMethodRule springMethodRule = new SpringMethodRule();
@Autowired
private Foo foo;
@Mock
private Runnable runnable;
@Test
public void method2() {
Mockito.doNothing().when(runnable).run();
foo.bar(runnable);
Mockito.verify(runnable).run();
}
}
@Configuration
class ConfigExample {
@Bean
public Foo Foo() {
return new Foo();
}
}
class Foo {
public void bar(Runnable invoke) {
invoke.run();
}
}