zoukankan      html  css  js  c++  java
  • 使用RunWith注解改变JUnit的默认执行类,并实现自已的Listener

    使用RunWith注解改变JUnit的默认执行类,并实现自已的Listener在平时的单元测试,如果不使用RunWith注解,那么JUnit将会采用默认的执行类Suite执行,如下类:
    public class TestClass {
    	@Test public void  t1(){}
    }
    
    JUnit允许用户指定其它的单元测试执行类,只需要我们的测试执行类继承类org.junit.runners.BlockJUnit4ClassRunner就可以了,Spring的执行类SpringJUnit4ClassRunner就是继承了该类。我们平时用Spring也比较多,为了能够更加方便的引用配置文件,我们单元测试就使用了Spring实现的执行类。此时的单元测试执行类将会看起来是这样:
    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(locations = { "classpath*:/spring1.xml", "classpath*:/spring2.xml" })
    @TestExecutionListeners( { DependencyInjectionTestExecutionListener.class, TransactionalTestExecutionListener.class })
    @Transactional
    public class TestClass {
    	@Inject
    	//这个类会在执行时被注入,这里是按类型注入,如果想按名称注入,需要加上@Named注解,如@Named("class1")
    	//实现类可以加上@Named("class1")注解,也可以是配置在配置文件中的
    	Class1 class1;
    	
    	@Test 
    	public void  t1(){}
    }
    

    以下分别对使用到的几个注解进行解释:

    @RunWith:这个是指定使用的单元测试执行类,这里就指定的是SpringJUnit4ClassRunner.class;

    @ContextConfiguration:这个指定Spring配置文件所在的路径,可以同时指定多个文件;

    @TestExecutionListeners:这个用于指定在测试类执行之前,可以做的一些动作,如这里的DependencyInjectionTestExecutionListener.class,就可以对一测试类中的依赖进行注入,TransactionalTestExecutionListener.class用于对事务进行管理;这两个都是Srping自带的; 我们也可以实现自己的Listener类来完成我们自己的操作,只需要继续类org.springframework.test.context.support.AbstractTestExecutionListener就可以了,具体可以参照DependencyInjectionTestExecutionListener.class的实现,后面我会贴出实例。 Listener实在实现类执行之前被执行、实现类的测试方法之前被执行,这与Listener的实现有关。

    @Transactional:这里的@Transactional不是必须的,这里是和@TestExecutionListeners中的TransactionalTestExecutionListener.class配合使用,用于保证插入的数据库中的测试数据,在测试完后,事务回滚,将插入的数据给删除掉,保证数据库的干净。如果没有显示的指定@Transactional,那么插入到数据库中的数据就是真实的插入了。

    我们的单元测试,通常涉及到数据库的操作,那我们就需要真实的从数据库中读取数据并进行逻辑处理,为了保证数据库的干净,也为了保证测试数据的准确性与正确性,我们最好是在做测试之前插入我们自己准备的测试数据,然后在测试完成后,将数据删除掉,这时我们就可以通过增加一个Listener,来准备我们需要的测试数据,并和上面的事务管理相结合,就不会真正的提交到数据库中去了。

    以下这个实例是一个简单的Listener实现,只是功能是把我们配置在method上面的注解里面的配置文件路径给打印出来,因为实现集成DBUnit并插入数据库的代码比较多,这里我就不贴出来了。1.首先我们需要准备一个注解,用来标识其带的参数为测试准备的数据文件:DBUnitTestData.java

    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.METHOD)
    @Inherited
    @Documented
    public @interface DBUnitTestData {
    
    	public String[] dataSetLocations();
    }
    
    2.编写Listener,这个Listener的名字就定义为DBUnitTestExecutionListener.class:DBUnitTestExecutionListener.java
    import org.springframework.test.context.TestContext;
    import org.springframework.test.context.TestExecutionListener;
    
    public class DBUnitTestExecutionListener implements TestExecutionListener {
    
    	public void prepareTestInstance(TestContext testContext) throws Exception {
    	}
    
    	public void beforeTestClass(TestContext testContext) throws Exception {
    		// Nothing to do
    	}
    
    	public void afterTestClass(TestContext testContext) throws Exception {
    		// Nothing to do
    	}
    
    	public void beforeTestMethod(TestContext testContext) throws Exception {
    		DBUnitTestData dbUnitRefresh = testContext.getTestMethod().getAnnotation(DBUnitTestData.class);
    		if (dbUnitRefresh == null) {
    			return;
    		}
    		String[] dataSetLocations = dbUnitRefresh.dataSetLocations();
    		loadTestData(testContext, dataSetLocations);
    	}
    
    	public void afterTestMethod(TestContext testContext) throws Exception {
    		// Nothing to do
    	}
    
    	private void loadTestData(TestContext testContext, String[] dataSetLocations) {
    		if (dataSetLocations == null || dataSetLocations.length == 0) {
    			return;
    		}
    		for (String dataSetLocation : dataSetLocations) {
    			//Do what you want to do with the data set files
    			System.out.println(dataSetLocation);
    		}
    	}
    
    }
    
    3.将Listener实现类加入到测试类的@TestExecutionListeners里面,在方法上面增加注解@DBUnitTestData,这个时候测试类将会是如下这样:
    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(locations = { "classpath*:/spring1.xml", "classpath*:/spring2.xml" })
    @TestExecutionListeners( { DependencyInjectionTestExecutionListener.class, TransactionalTestExecutionListener.class,DBUnitTestExecutionListener.class })
    @Transactional
    public class TestClass {
    	@Inject
    	//这个类会在执行时被注入,这里是按类型注入,如果想按名称注入,需要加上@Named注解,如@Named("class1")
    	//实现类可以加上@Named("class1")注解,也可以是配置在配置文件中的
    	Class1 class1;
    	
    	@Test 
    	@DBUnitTestData(dataSetLocations={"classpath:/testData/testData1.xml","classpath:/testData/testData2.xml"})
    	public void  t1(){}
    }
    
    4.执行这个方法就可以看到@DBUnitTestData注解的数据文件路径给打印出来了。

    再分享一下我老师大神的人工智能教程吧。零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!https://blog.csdn.net/jiangjunshow

  • 相关阅读:
    SCAU 9504 面试
    SCAU 9503 懒人选座位
    SCAU 8628 相亲
    SCAU 10691 ACM 光环
    SCAU 8626 原子量计数
    SCAU 10674 等差对
    HDU ACM 1048 The Hardest Problem Ever (水题)
    SCAU 9502 ARDF
    SCAU 10686 DeathGod不知道的事情
    SCAU 8629 热身游戏(高精度)
  • 原文地址:https://www.cnblogs.com/skiwdhwhssh/p/10295643.html
Copyright © 2011-2022 走看看