gpt4 book ai didi

spring - 你能想出更好的方法来使用 Spring 在每个测试类中只加载一次 DBbUnit 吗?

转载 作者:行者123 更新时间:2023-12-02 00:27:34 25 4
gpt4 key购买 nike

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

  1. 每个测试类只加载一次数据集
  2. 支持多个数据源和 ApplicationContext 中未命名为“dataSource”的数据源
  3. 不严格要求回滚插入的 DBUnit 数据集

虽然下面的代码有效,但困扰我的是我的测试类有静态方法 beforeClassWithApplicationContext() 但它不能属于接口(interface),因为它是静态的。因此,我对反射的使用是以一种非类型安全的方式使用的。有没有更优雅的解决方案?

/**
* 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)

关于spring - 你能想出更好的方法来使用 Spring 在每个测试类中只加载一次 DBbUnit 吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8313219/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com