如何创建spring参数化事务测试

时间:2013-02-12 13:19:23

标签: java spring junit

在我的测试中我需要使用spring依赖注入事务和参数。我找到了如何使用参数化和DI的示例:

@RunWith(value = Parameterized.class)
@ContextConfiguration(locations = { "classpath:applicationContextTest-business.xml" })
public class TournamentServiceTest {

@Autowired
TournamentService tournamentService;

    public TournamentServiceTest(int playerCount) {
        this.playerCount = playerCount;
    }

    @Parameters
    public static List<Object[]> data() {
        final List<Object[]> parametry = new ArrayList<Object[]>();
        parametry.add(new Object[] { 19 });
        parametry.add(new Object[] { 20 });
        return parametry;
    }

    @Before
    public void vytvorTurnaj() throws Exception {
        testContextManager = new TestContextManager(getClass());
        testContextManager.prepareTestInstance(this);
    }

@Test
public void test1() {
     Assert.assertFalse(false);
}

}

此示例有效。现在我需要向这个类添加事务:

@RunWith(value = Parameterized.class)
@ContextConfiguration(locations = { "classpath:applicationContextTest-business.xml" })
@Transactional
@TransactionConfiguration(defaultRollback = true)
public class TournamentServiceTest ...

当我添加这两个新行时,此测试抛出异常:

org.springframework.aop.framework.AopConfigException: Could not generate CGLIB subclass of class [class org.toursys.processor.service.TournamentServiceTest]: Common causes of this problem include using a final class or a non-visible class; nested exception is java.lang.IllegalArgumentException: Superclass has no null constructors but no arguments were given

因为他想添加空构造函数:

public TournamentServiceTest() {
    this.playerCount = 20;
}

但是我无法添加它,因为然后参数化不能运行此测试。我怎么能解决这个问题?

2 个答案:

答案 0 :(得分:2)

Spring TestContext Framework目前正在进行not support Parameterized tests。您需要一个自定义规则或运行器。有空位 pull request,您可以从那里获取代码。

从Spring 4.2开始,您可以使用

@ClassRule
public static final SpringClassRule SPRING_CLASS_RULE = new SpringClassRule();

@Rule
public final SpringMethodRule springMethodRule = new SpringMethodRule();

答案 1 :(得分:0)

我有这个CallbackParams的JUnit-runner - http://callbackparams.org

它提供参数化,但它也可以将实际的测试执行传递给您选择的JUnit-runner。如果您传递给SpringJUnit4ClassRunner,您将获得“弹簧参数化事务测试”,并提供事务支持等...

@RunWith(CallbackParamsRunner.class)
@WrappedRunner(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:applicationContextTest-business.xml"})
@Transactional
@TransactionConfiguration(defaultRollback = true)
public class TestTournamentService {

    enum PlayerCountData {
        _19, _20;

        final int value = Integer.parseInt(name().substring(1));
    }

    @ParameterizedValue PlayerCountData playerCount;

    @Autowired TournamentService tournamentService;

    @Test
    public void test1() {
        Assert.assertNotNull(
                "TournamentService should have been autowired",
                tournamentService);
        Assert.assertTrue("Player-count value greater than 18",
                18 < playerCount.value);
        Assert.assertTrue("Player-count value less than 21",
                playerCount.value < 21);
    }
}

正如您所看到的,参数化解决方案略有不同。这是因为CallbackParams没有优先考虑原始数据的参数化,原因在于教程中解释的原因: http://callbackparams.org/index.html#articles

使用CallbackParams,参数值是根据参数类型确定的,因此不能直接使用int参数。 - 上面的示例使用参数类型的PlayerCountData,并从枚举常量的名称中解析int值。

运行测试类导致两个具有以下名称的测试运行:

  • TEST1 [playerCount = _19]
  • TEST1 [playerCount = _20]

也许这就是你要找的东西。