【问题标题】:Is there a way I can run TestNG tests against multiple interface implementations (DataSources)?有没有办法可以针对多个接口实现(数据源)运行 TestNG 测试?
【发布时间】:2012-03-11 15:53:52
【问题描述】:

我正在寻找一种方法来针对多个 DataSources 运行一些 TestNG 测试。我已经看到了 TestNG 的 DataProvider 选项,但它们并没有完全满足我的要求。我想对我的 MyBatis 映射器运行一些非常简单的测试,主要是为了确保我没有任何简单的语法错误、拼写错误等。现在,我有一个这样的基础测试类:

public class MapperTestBaseH2 {
    protected SqlSessionManager sessionManager;

    @BeforeClass
    public void beforeClass() throws SQLException, LiquibaseUpdateException {
        JdbcDataSource h2DataSource = new JdbcDataSource();
        h2DataSource.setURL("jdbc:h2:mem:test-db;DB_CLOSE_DELAY=-1");

        sessionManager = MyBatisUtils.createSqlSessionManager(h2DataSource);
        LiquibaseUpdater.update(h2DataSource.getConnection(), LiquibaseUpdater.DEFAULT_CONTEXTS);
    }

    @BeforeMethod
    public void beforeMethod() {
        sessionManager.startManagedSession();
    }

    @AfterMethod
    public void afterMethod() {
        sessionManager.rollback();
    }
}

然后我为每个映射器创建一个测试:

public class SequenceMapperTest extends MapperTestBaseH2 {
    private SequenceMapper sequenceMapper;

    @BeforeClass
    @Override
    public void beforeClass() throws SQLException, LiquibaseUpdateException {
        super.beforeClass();
        sequenceMapper = super.sessionManager.getMapper(SequenceMapper.class);
    }

    @Test
    public void selectBidSequenceTest() {
        sequenceMapper.selectSequence(Sequences.BID_SEQ);
    }

    @Test
    public void updateBidSequenceTest() {
        sequenceMapper.updateSequence(sequenceMapper.selectSequence(Sequences.BID_SEQ));
    }
}

我想做的是运行每个测试类两次(或更多),每次使用不同的SqlSessionManager。我可以使用 TestNG 的 DataProvider 以多个 SqlSessionManagers 运行每个测试,但是我必须在每个测试中而不是在 @BeforeMethod 中启动和回滚会话。

有没有简单的方法来完成我想要的?

【问题讨论】:

  • 你使用的是Spring之类的DI容器吗?
  • @AmirPashazadeh 不。我看了一点 Guice,但是,考虑到我正在做一些相当小的事情,它增加的复杂性比它消耗的要多得多。

标签: java testng mybatis


【解决方案1】:

我想我在偶然发现this post. 之后已经弄清楚了,诀窍是使用@Factory@DataProvider 的组合。首先,我创建了一个抽象基类来管理提供者和事务。

public abstract class MyBatisTestBase {
    public abstract SqlSessionManager getSessionManager();

    @BeforeMethod
    public void beforeMethod() {
        getSessionManager().startManagedSession();
    }

    @AfterMethod
    public void afterMethod() {
        getSessionManager().rollback();
    }

    @DataProvider(name = "sql-session-manager-provider")
    public static Object[][] sqlSessionManagerProvider() throws SQLException, LiquibaseUpdateException {
        return new Object[][] {
                {createDerbySessionManager()},
                {createH2SessionManager()}
        };
    }

    private static SqlSessionManager createDerbySessionManager() throws SQLException, LiquibaseUpdateException {
        EmbeddedDataSource40 dataSource = new EmbeddedDataSource40();
        dataSource.setDatabaseName("memory:test-db");
        dataSource.setCreateDatabase("create");

        LiquibaseUtils.update(dataSource.getConnection(), LiquibaseUtils.DEFAULT_CONTEXTS);
        return MyBatisUtils.createSqlSessionManager(dataSource);
    }

    private static SqlSessionManager createH2SessionManager() throws SQLException, LiquibaseUpdateException {
        JdbcDataSource dataSource = new JdbcDataSource();
        dataSource.setURL("jdbc:h2:mem:test-db;DB_CLOSE_DELAY=-1");

        LiquibaseUtils.update(dataSource.getConnection(), LiquibaseUtils.DEFAULT_CONTEXTS);
        return MyBatisUtils.createSqlSessionManager(dataSource);
    }
}

然后我在扩展类的构造函数上使用@Factory注解。这具有从我的@DataProvider 为每个SqlSessionManager 创建一个测试类实例的效果。

public class SequenceMapperTest extends MyBatisTestBase {
    private final SqlSessionManager sessionManager;
    private final SequenceMapper sequenceMapper;

    @Factory(dataProvider = "sql-session-manager-provider")
    public SequenceMapperTest(SqlSessionManager sessionManager) {
        this.sessionManager = sessionManager;
        this.sequenceMapper = sessionManager.getMapper(SequenceMapper.class);
    }

    @Test
    public void selectBidSequenceTest() {
        sequenceMapper.selectSequence(Sequences.BID_SEQ);
    }

    @Test
    public void updateBidSequenceTest() {
        sequenceMapper.updateSequence(sequenceMapper.selectSequence(Sequences.BID_SEQ));
    }

    @Override
    public SqlSessionManager getSessionManager() {
        return this.sessionManager;
    }
}

当我运行测试时,会创建两个SequenceMapperTest 实例,每个SqlSessionManager 对应一个我在@DataProvider 中设置的实例。到目前为止,它似乎工作正常,但我的 IDE (IntelliJ IDEA) 在拆分每个单独测试的日志输出时遇到了一些问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-31
    • 2014-02-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多