[英]Spring Transactional Parameterized Test and Autowiring
有没有办法让一个扩展 AbstractTransactionalJUnit4SpringContexts 的类与 JUnit 自己的 @RunWith(Parameterized.class) 很好地配合,以便标记为 Autowired 的字段正确连接?
@RunWith(Parameterized.class)
public class Foo extends AbstractTransactionalJUnit4SpringContextTests {
@Autowired private Bar bar
@Parameters public static Collection<Object[]> data() {
// return parameters, following pattern in
// http://junit.org/apidocs/org/junit/runners/Parameterized.html
}
@Test public void someTest(){
bar.baz() //NullPointerException
}
}
您可以使用 Spring 中的 TestContextManager。 在这个例子中,我使用的是理论而不是参数化。
@RunWith(Theories.class)
@ContextConfiguration(locations = "classpath:/spring-context.xml")
public class SeleniumCase {
@DataPoints
public static WebDriver[] drivers() {
return new WebDriver[] { firefoxDriver, internetExplorerDriver };
}
private TestContextManager testContextManager;
@Autowired
SomethingDao dao;
private static FirefoxDriver firefoxDriver = new FirefoxDriver();
private static InternetExplorerDriver internetExplorerDriver = new InternetExplorerDriver();
@AfterClass
public static void tearDown() {
firefoxDriver.close();
internetExplorerDriver.close();
}
@Before
public void setUpStringContext() throws Exception {
testContextManager = new TestContextManager(getClass());
testContextManager.prepareTestInstance(this);
}
@Theory
public void testWork(WebDriver driver) {
assertNotNull(driver);
assertNotNull(dao);
}
}
我在这里找到了这个解决方案: 如何使用 Spring 进行参数化/理论测试
为此,您可以使用SpringClassRule和SpringMethodRule
@RunWith(Parameterized.class)
@ContextConfiguration(...)
public class FooTest {
@ClassRule
public static final SpringClassRule SPRING_CLASS_RULE = new SpringClassRule();
@Rule
public final SpringMethodRule springMethodRule = new SpringMethodRule();
@Autowired
private Bar bar
@Parameters
public static Collection<Object[]> data() {
// return parameters, following pattern in
// http://junit.org/apidocs/org/junit/runners/Parameterized.html
}
@Test
public void someTest() {
bar.baz() //NullPointerException
}
}
不,你不能。 超类有:
@RunWith(SpringJUnit4ClassRunner.class)
这确保测试在 spring 上下文中运行。 如果你更换它,你就会失去这个。
我想到的替代方案是扩展SpringJunit4ClassRunner
,在那里提供您的自定义功能并将其与@RunWith(..)
。 因此,您将拥有 spring 上下文 + 您的附加功能。 它将调用super.createTest(..)
然后在测试中执行其他内容。
以下是我在 Spring Boot 1.5.7
:
将@RunWith(Parameterized.class)
注释添加到您的类
将您的依赖项作为类字段注入:
@Autowired private Bar bar;
将您的参数添加为类字段:
private final int qux; private final Boolean corge; private final String grault;
添加构造函数以初始化参数,如下所示:
public Foo(int qux, Boolean corge, String grault) throws Exception { this.qux = qux; this.corge = corge; this.grault = grault; new TestContextManager(getClass()).prepareTestInstance(this); }
添加一个静态方法data
,它返回一个包含每次迭代时参数值的集合,尊重它们传递给构造函数的顺序:
@Parameterized.Parameters public static Collection<Object[]> data() { return Arrays.asList(new Object[][]{ { 1, Boolean.FALSE, "Hello" }, { 2, Boolean.TRUE, null }, { 3, null, "world" } }); }
使用上面声明的类字段编写您的测试,如下所示:
@Test public void someTest(){ // Some arrangements // Some actions assertThat(myTestedIntValue, is(equalTo(qux)); assertThat(myTestedBooleanValue, is(equalTo(corge)); assertThat(myTestedStringValue, is(equalTo(grault)); }
我不得不以编程方式处理事务(参见http://www.javathinking.com/2011/09/junit-parameterized-test-with-spring-autowiring-and-transactions/ ):
@RunWith(Parameterized.class)
@ContextConfiguration(locations = "classpath*:/testContext.xml")
public class MyTest {
@Autowired
PlatformTransactionManager transactionManager;
private TestContextManager testContextManager;
public MyTest (... parameters for test) {
// store parameters in instance variables
}
@Before
public void setUpSpringContext() throws Exception {
testContextManager = new TestContextManager(getClass());
testContextManager.prepareTestInstance(this);
}
@Parameterized.Parameters
public static Collection<Object[]> generateData() throws Exception {
ArrayList list = new ArrayList();
// add data for each test here
return list;
}
@Test
public void validDataShouldLoadFully() throws Exception {
new TransactionTemplate(transactionManager).execute(new TransactionCallback() {
public Object doInTransaction(TransactionStatus status) {
status.setRollbackOnly();
try {
... do cool stuff here
} catch (Exception e) {
throw new RuntimeException(e);
}
return null;
}
});
}
受 Simon 解决方案的启发,您还可以将 TestContextManager 与参数化运行程序一起使用:
@RunWith(Parameterized.class)
@ContextConfiguration(locations = "classpath:/spring-context.xml")
public class MyTestClass {
@Parameters public static Collection data() {
// return parameters, following pattern in
// http://junit.org/apidocs/org/junit/runners/Parameterized.html
}
@Before
public void setUp() throws Exception {
new TestContextManager(getClass()).prepareTestInstance(this);
}
}
这是完整的例子
在这种情况下,我不确定如何处理 @Transactional。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.