您能想到一种更好的方法,即使用Spring在每个测试类中仅加载一次DBbUnit吗?

我意识到最佳实践可能会建议在每个@Test方法上加载测试数据,但是这对于DBUnit而言可能会非常缓慢,因此我想出了以下解决方案,每个类只能加载一次:

>每个测试类别仅加载一次数据集
>支持多个数据源以及ApplicationContext中未命名为“ dataSource”的数据源
>并非严格要求回滚插入的DBUnit数据集

虽然下面的代码有效,但令我感到困扰的是我的Test类在类ClassClassApplicationApplicationContext()之前有静态方法,但由于它是静态的,所以不能属于接口.因此,以非类型安全的方式使用我对Reflection的使用.有没有更优雅的解决方案?

/**
 * My Test class
 */
@RunWith(SpringJUnit4ClassRunner.class)
@TestExecutionListeners({DependencyInjectionTestExecutionListener.class,DirtiesContextTestExecutionListener.class,DbunitLoadOnceTestExecutionListener.class})
@ContextConfiguration(locations={"classpath:resources/spring/applicationContext.xml"})
public class TestClass {

    public static final String TEST_DATA_FILENAME = "Scenario-1.xml";

    public static void beforeClassWithApplicationContext(ApplicationContext ctx) throws Exception {

        DataSource ds = (DataSource)ctx.getBean("dataSourceXyz");

        IDatabaseConnection conn = new DatabaseConnection(ds.getConnection());

        IDataSet dataSet = DbUnitHelper.getDataSetFromFile(conn,TEST_DATA_FILENAME);

        InsertIdentityOperation.CLEAN_INSERT.execute(conn,dataSet);
    }

    @Test
    public void somethingTotest() {
        // do stuff...
    }
}

/**
 * My new custom TestExecutioner
 */
public class DbunitLoadOnceTestExecutionListener extends AbstractTestExecutionListener {

    final String methodName = "beforeClassWithApplicationContext";

    @Override
    public void beforeTestClass(TestContext testContext) throws Exception {

        super.beforeTestClass(testContext);        

        Class<?> clazz = testContext.getTestClass();

        Method m = null;

        try {
            m = clazz.getDeclaredMethod(methodName,ApplicationContext.class);
        }
        catch(Exception e) {
            throw new Exception("Test class must implement " + methodName + "()",e);
        }

        m.invoke(null,testContext.getApplicationContext());
    }
}

我曾经想到的另一种想法可能是创建一个静态单例类,以保存对ApplicationContext的引用,并从DbunitLoadOnceTestExecutionListener.beforeTestClass()填充它.然后,我可以从TestClass上定义的标准@BeforeClass方法中检索该单例引用.我上面调用每个TestClass的代码看起来有些混乱.

最佳答案
在得到Matt和JB的有益反馈之后,这是实现所需结果的简单得多的解决方

/**
 * My Test class
 */
@RunWith(SpringJUnit4ClassRunner.class)
@TestExecutionListeners({DependencyInjectionTestExecutionListener.class,DbunitLoadOnceTestExecutionListener.class})
@ContextConfiguration(locations={"classpath:resources/spring/applicationContext.xml"})
public class TestClass {

    private static final String TEST_DATA_FILENAME = "Scenario-1.xml";

    // must be static
    private static volatile boolean isDataSetLoaded = false;

    // use the Qualifier to select a specific dataSource
    @Autowired
    @Qualifier("dataSourceXyz")
    private DataSource dataSource;

    /**
     * For performance reasons,we only want to load the DBUnit data set once per test class 
     * rather than before every test method.
     * 
     * @throws Exception
     */
    @Before
    public void before() throws Exception {

        if(!isDataSetLoaded) {

            isDataSetLoaded = true;

            IDatabaseConnection conn = new DatabaseConnection(dataSource.getConnection());

            IDataSet dataSet = DbUnitHelper.getDataSetFromFile(conn,TEST_DATA_FILENAME);

            InsertIdentityOperation.CLEAN_INSERT.execute(conn,dataSet);
        }       
    }

    @Test
    public void somethingTotest() {
        // do stuff...
    }
}

类DbunitLoadOnceTestExecutionListener不再需要,已被删除.它只是表明,阅读所有奇特的技巧有时可能会使您自己的判断蒙蔽:o)

相关文章

这篇文章主要介绍了spring的事务传播属性REQUIRED_NESTED的原...
今天小编给大家分享的是一文解析spring中事务的传播机制,相...
这篇文章主要介绍了SpringCloudAlibaba和SpringCloud有什么区...
本篇文章和大家了解一下SpringCloud整合XXL-Job的几个步骤。...
本篇文章和大家了解一下Spring延迟初始化会遇到什么问题。有...
这篇文章主要介绍了怎么使用Spring提供的不同缓存注解实现缓...