论坛首页 Java企业应用论坛

扩展Spring junit4 的TestExecutionListener

浏览 2341 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2009-04-24   最后修改:2009-05-07
web单元测试经常会在执行前准备一些数据
执行完毕后删除这些数据  如下伪代码
public void testFindUser(){
    jdbcTemplate.insert('insert into user...');
    jdbcTemplate.insert('insert into user...');

    User u = userManager.findUser("....");
    
    Assert();
    
    jdbcTemplate.delete();
}

这很烦!
采用jdbcTemplate或一些其他的方法也很烦
毕竟要写一堆无关紧要的代码

先看我们改进后的效果

BeforeMethod 是在执行测试方法前准备数据
AfterMethod  来清理数据
其value值是一些 sql语句

public class MessageManagerTest extends JUnit4TestCase {
	
	@Autowired
	MessageManager messageManager;
	
	@Test
	@BeforeMethod({
		"insert into sns_user(id, email,password, nickname, enabled) values ('10','100@justel.com.cn','password','haha', 1);", 
		"insert into sns_user(id, email,password, nickname, enabled) values ('11','101@justel.com.cn','password','haha2', 1);"
	})
	
	@AfterMethod({"delete from sns_message", "delete from sns_user"})
	
	public void send(){
		Message msg = new Message();
		try {
			messageManager.send(msg);
		} catch (UserNotExistException e) {
			Assert.fail();
		}
		
		int count = simpleJdbcTemplate.queryForInt("select count(*) from sns_message where id = ?", msg.getId());
		Assert.assertEquals(1, count);
	}
	
}


会写sql就ok了 不用其他知识


再来看看具体实现

很简单扩展一下spring 提供的TestExecutionListener接口就行了

public interface TestExecutionListener {
	
	void prepareTestInstance(TestContext testContext) throws Exception;
//测试前执行
	void beforeTestMethod(TestContext testContext) throws Exception;
//测试后执行
	void afterTestMethod(TestContext testContext) throws Exception;

}


扩展后的类
public class PreparedDataTestExecutionListener extends AbstractTestExecutionListener {
	
	@Override
	public void beforeTestMethod(TestContext testContext) throws Exception {
		BeforeMethod beforeMethod = testContext.getTestMethod().getAnnotation(BeforeMethod.class);
		if(beforeMethod != null){
			executeBeforeMethod(testContext, beforeMethod);
		}
	}
	
	@Override
	public void afterTestMethod(TestContext testContext) throws Exception {
		AfterMethod afterMethod = testContext.getTestMethod().getAnnotation(AfterMethod.class);
		if(afterMethod != null){
			executeAfterMethod(testContext, afterMethod);
		}
	} 
	
	/**
	 * 准备数据
	 */
	protected void executeBeforeMethod(TestContext testContext, BeforeMethod beforeMethod){
		DataSource dataSource = (DataSource)testContext.getApplicationContext().getBean("dataSource");
		JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
		
		String[] sqls = beforeMethod.value();
		for (String sql : sqls) {
			jdbcTemplate.execute(sql);
		}
	}
	

	/**
	 * 清理数据
	 */
	protected void executeAfterMethod(TestContext testContext, AfterMethod afterMethod){
		DataSource dataSource = (DataSource)testContext.getApplicationContext().getBean("dataSource");
		JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
		
		String[] sqls = afterMethod.value();
		for (String sql : sqls) {
			jdbcTemplate.execute(sql);
		}
	}
}


实际上是将jdbcTemplate转移了个位置而已

这个PreparedDataTestExecutionListener怎么用呢
接着看代码
@ContextConfiguration(locations = { "classpath:/application-test.xml" }) 
@TestExecutionListeners({PreparedDataTestExecutionListener.class})
public class JUnit4TestCase extends AbstractTransactionalJUnit4SpringContextTests{
	
}


这样你的testcase只要继承JUnit4TestCase就可以使用BeforeMethod和AfterMethod了

附上BeforeMethod和AfterMethod

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface BeforeMethod {
	String[] value() default {};
}

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface AfterMethod {
	String[] value() default {};
}


论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics