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

您能想到一种更好的方法,即使用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, DirtiesContextTestExecutionListener.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)

标签:junit,dbunit,spring
来源: https://codeday.me/bug/20191202/2085366.html