junit规则_JUnit规则

junit规则

介绍

在本文中,我想展示一个示例,说明如何使用JUnit Rule简化测试。

最近,我继承了一个相当复杂的系统,并未对所有内容进行测试。 甚至经过测试的代码也很复杂。 通常,我看到缺乏测试隔离。 (我将写一个关于使用Legacy Code的不同博客)。

我正在修复的测试(和代码)之一实际上是将多个组件一起测试。 它还连接到数据库。 它测试一些逻辑和组件之间的交集。 如果代码没有在完全不同的位置编译,则测试无法运行,因为它加载了所有Spring上下文。 其结构是在测试(任何类)之前启动所有Spring上下文。 这些测试扩展了BaseTest,该加载了所有Spring上下文。

BaseTest还使用@After方法清除数据库。

重要说明:本文是关于更改测试的,并非结构完全正确。 在创建新代码和测试时,应该将它们隔离,一事不做。更好的测试应该使用模拟数据库/依赖项等。修复测试和重构后,我将充满信心进行更多更改。

回到我们的话题…

因此,我得到的是测试套件运行缓慢,没有隔离,甚至由于不相关的问题而导致测试运行出现问题。 因此,我决定将数据库连接的上下文加载与清理数据库分开。

方法

为了实现这一点,我做了三件事:首先是更改测试类的继承。 它停止继承BaseTest。 相反,它继承了AbstractJUnit4SpringContextTests现在,我可以为每个测试创建自己的上下文,而不加载所有内容。

现在我需要两个规则,@ClassRule和@Rule @ClassRule将负责数据库连接@Rule将在每次测试之后/之前清理数据库。

但是首先, 什么是JUnit规则?
简短的解释是,它们提供了拦截测试方法的可能性,类似于AOP概念。 @Rule允许我们在方法实际运行之前和之后拦截方法。 @ClassRule拦截测试类的运行。 一个非常有名的@Rule是JUnit的TemporaryFolder

(类似于@ Before,@ After和@BeforeClass)。

创建@Rule

最简单的部分是创建一个在测试方法之前和之后清理数据库的规则。 您需要实现TestRule ,它具有一种方法: 语句apply(Statement base,Description description); 你可以做很多。 我发现通常我会有一个扩展Statement的内部类。 我创建的规则并未创建数据库连接,而是在构造函数中获得了它。

这是完整的代码:

public class DbCleanupRule implements TestRule {
	private final DbConnectionManager connection;

	public MongoCleanupRule(DbConnectionManager connection) {
		this.connection = connection;
	}

	@Override
	public Statement apply(Statement base, Description description) {
		return new MongoCleanupStatement(base, connection);
	}

	private static final class DbCleanupStatement extends Statement {
		private final Statement base;
		private final DbConnectionManager connection;
		
		private MongoCleanupStatement(Statement base, DbConnectionManager connection) {
			this.base = base;
			this.connection = connection;
		}

		@Override
		public void evaluate() throws Throwable {
			try {
				cleanDb();
				base.evaluate();
			} finally {
				cleanDb();
			}
		}
		
		private void cleanDb() {
			connection.doTheCleanup();
		}
	}
}

创建@ClassRule

ClassRule实际上也是TestRule。 与Rule的唯一区别是我们在测试代码中如何使用它。 我将在下面显示。

创建此规则的挑战在于,我想使用Spring上下文来获取正确的连接。
这是代码:
(ExternalResource是TestRule)

public class DbConnectionRule extends ExternalResource {
	private DbConnectionManager connection;

	public DbConnectionRule() {
	}
	
	@Override
	protected void before() throws Throwable {
		ClassPathXmlApplicationContext ctx = null;
		try {
			ctx = new ClassPathXmlApplicationContext("/META-INF/my-db-connection-TEST-ctx.xml");
			mongoDb = (DbConnectionManager) ctx.getBean("myDbConnection");
		} finally {
		    if (ctx != null) {
		        ctx.close();
		    }
		}
	}
	
	@Override
	protected void after() {
	}
	
	public DbConnectionManager getDbConnecttion() {
		return connection;
	}
}

(您是否看到我可以使DbCleanupRule继承ExternalResource?)

使用它

最后一部分是我们如何使用规则。 @Rule必须是公共字段。 @ClassRule必须是公共静态字段。

那里是:

@ContextConfiguration(locations = { "/META-INF/one-dao-TEST-ctx.xml", "/META-INF/two-TEST-ctx.xml" })
public class ExampleDaoTest extends AbstractJUnit4SpringContextTests {

	@ClassRule
	public static DbCleanupRule  connectionRule = new DbCleanupRule ();
	
	@Rule
	public DbCleanupRule dbCleanupRule = new DbCleanupRule(connectionRule.getDbConnecttion()); 

	@Autowired
	private ExampleDao classToTest;

	@Test
	public void foo() {
	}
}

就这样。
希望能帮助到你。

翻译自: https://www.javacodegeeks.com/2014/09/junit-rules-3.html

junit规则

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值