Junit常用注解
0x01 摘要
本文简要说下junit里面常用注解的含义和使用,还会总结一些常用的Assert判断语句。
0x02 常用Junit注解
2.1 @Test
用在方法上,定义该方法是测试方法。
注意:测试方法必须是public void,但可以抛异常,不过一般不这么做。
例子:
@Test (timeout = 30000)
public void testRMAppSubmitInvalidResourceRequest() throws Exception {
asContext.setResource(Resources.createResource(
YarnConfiguration.DEFAULT_RM_SCHEDULER_MAXIMUM_ALLOCATION_MB + 1));
// submit an app
try {
appMonitor.submitApplication(asContext, "test");
Assert.fail("Application submission should fail because resource" +
" request is invalid.");
} catch (YarnException e) {
// Exception is expected
// TODO Change this to assert the expected exception type - post YARN-142
// sub-task related to specialized exceptions.
Assert.assertTrue("The thrown exception is not" +
" InvalidResourceRequestException",
e.getMessage().contains("Invalid resource request"));
}
}2.2 @BeforeClass
2.2.1 含义
用来修饰所有@Test方法之前只会运行一次的方法。
注意:需用public static void 修饰。
2.2.2 用途
当你的测试中多个方法都会用到的一些公共方法可以抽取到用@BeforeClass修饰的方法汇总,如创建数据库驱动等。
2.2.3 示例
@BeforeClass
public static void loadDriver(){
try {
Class.forName("org.apache.phoenix.queryserver.client.Driver");
} catch (ClassNotFoundException e) {
logger.error("an exception happened while load driver:", e);
}
}2.3 @AfterClass
2.3.1 含义
@AfterClass和前面提到的@BeforeClass类似,但是在所有@Test方法之后运行一次。
注意:需用public static void 修饰。
2.3.2 用途
一般他被来处理一些资源清理工作,如关闭数据库连接等。
2.3.3 示例
@AfterClass
public static void closeConnections(){
for(Connection conn : connectionList){
try {
conn.close();
} catch (SQLException e) {
logger.error("an exception happened while close connection:", e);
}
}
}2.4 @Before
2.4.1 含义
@Before与@BeforeClass类似,他们最大区别在于@Before会在每个@Test方法运行之前都会运行一次。
注意:必须用public void修饰,不能加static。
2.4.2 用途
用于每个测试用例都需要的单独的方法,比如获取插入一条记录到数据。
2.4.3 示例
@Before
public void setUp() {
long now = System.currentTimeMillis();
rmContext = mockRMContext(1, now - 10);
ResourceScheduler scheduler = mockResourceScheduler();
Configuration conf = new Configuration();
ApplicationMasterService masterService =
new ApplicationMasterService(rmContext, scheduler);
appMonitor = new TestRMAppManager(rmContext,
new ClientToAMTokenSecretManagerInRM(), scheduler, masterService,
new ApplicationACLsManager(conf), conf);
appId = MockApps.newAppID(1);
RecordFactory recordFactory = RecordFactoryProvider.getRecordFactory(null);
asContext =
recordFactory.newRecordInstance(ApplicationSubmissionContext.class);
asContext.setApplicationId(appId);
asContext.setAMContainerSpec(mockContainerLaunchContext(recordFactory));
asContext.setResource(mockResource());
setupDispatcher(rmContext, conf);
}2.5 @After
2.5.1 含义
@After与@AfterClass类似,他们最大区别在于@After会在每个@Test方法运行之后都会运行一次。
注意:必须用public void修饰,不能加static。
2.5.2 用途
可以用来清理每个@Test用@Before创建的单独资源、恢复测试初始状态等。
2.5.3 示例
@After
public void tearDown() {
setAppEventType(RMAppEventType.KILL);
((Service)rmContext.getDispatcher()).stop();
}2.6 @Runwith
2.6.1 含义
首先要分清几个概念:测试方法、测试类、测试集、测试运行器:
- 其中测试方法就是用
@Test注解的一些函数 - 测试类是包含一个或多个测试方法的一个
Test.java文件 - 测试集是一个
suite,可能包含多个测试类 - 测试运行器则决定了用什么方式偏好去运行这些测试集/类/方法
而@Runwith就是放在测试类名之前,用来确定这个类怎么运行的。也可以不标注,会使用默认运行器。
常见的运行器有:
- @RunWith(Parameterized.class) 参数化运行器,配合@Parameters使用junit的参数化功能
- @RunWith(Suite.class)
@SuiteClasses({ATest.class,BTest.class,CTest.class})
测试集运行器配合使用测试集功能
- @RunWith(JUnit4.class)
junit4的默认运行器
- @RunWith(JUnit38ClassRunner.class)
用于兼容junit3.8的运行器
- 一些其它运行器具备更多功能。例如@RunWith(SpringJUnit4ClassRunner.class)集成了spring的一些功能
2.7 @Parameters
用于使用参数化功能。
2.8 @Rule和@TestRule
2.8.1 含义
- @Rule
方法级别,每个测试方法执行时都会执行被@Rule注解的成员变量的实现自TestRule的apply方法,和@Before类似。 - @ClassRule
类级别,测试类执行时仅会执行一次被@ClassRule注解的静态变量的方法,和@BeforeClass)类似。
2.8.2 用途
Before注解只能作用域当前测试类和子类,而实现了TestRule的类可以被用于多个测试类,可增加代码复用度。
2.8.3 示例
- Timeout
为所有测试方法指定统一超时时间
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.Timeout;
import java.util.concurrent.TimeUnit;
public class TimeoutTest {
@Rule
public Timeout timeout = new Timeout(1000,TimeUnit.MILLISECONDS);
// 测试失败,超时
// org.junit.runners.model.TestTimedOutException: test timed out after 1000 milliseconds
@Test
public void test1() throws Exception {
Thread.sleep(2000);
}
// 测试成功
@Test
public void test2() throws Exception {
Thread.sleep(500);
}
// 测试成功
@Test
public void test3() throws Exception {
Thread.sleep(1000);
}
}- TestName
可获取测试方法名字
import static org.junit.Assert.*;
import org.junit.*;
import org.junit.rules.TestName;
public class TestNameTest {
@Rule
public TestName name = new TestName();
@Test
public void testA() {
System.out.println(name.getMethodName());
assertEquals("testA", name.getMethodName());
}
@Test
public void testB() {
System.out.println(name.getMethodName());
// fail
assertEquals("testC", name.getMethodName());
}
}- TemporaryFolder
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import java.io.File;
import java.io.IOException;
/**
* @Author: chengc
* @Date: 2020-03-12 12:57
*/
public class TemporaryFolderTest {
// 使用系统临时目录,也可在构造方法上加入路径来指定临时目录
@Rule
public TemporaryFolder tempFolder = new TemporaryFolder(new File("/Users/chengc/cc/work/projects/javaDemos/src/main/resources"));
@Test
public void testTempFolderRule() throws IOException {
// 在系统的临时目录下创建目录,当测试方法执行完毕自动删除
File directory = tempFolder.newFolder("test");
System.out.println(directory.getAbsoluteFile());
// 在系统的临时目录下创建文件,当测试方法执行完毕自动删除
File file1 = tempFolder.newFile("tmptest.txt");
File file2 = tempFolder.newFile("tmptest2.txt");
System.out.println(file1.getName());
System.out.println(file2.getParentFile());
System.out.println(file2.getAbsoluteFile());
System.out.println(file2.getCanonicalPath());
}
}- 自定义Rule
实现TestRule即可:
import org.junit.rules.TestRule;
import org.junit.runner.Description;
import org.junit.runners.model.Statement;
/**
* @Author: chengc
* @Date: 2020-03-12 13:19
*/
public class AgeRule implements TestRule {
private int age;
public AgeRule(int age){
this.age = age;
}
public int getAge() {
return age;
}
@Override
public Statement apply(Statement base, Description description) {
return new Statement() {
@Override
public void evaluate() throws Throwable {
//执行一次测试方法
base.evaluate();
}
};
}
}
import org.junit.Assert;
import org.junit.Rule;
import org.junit.Test;
import java.util.Random;
/**
* @Author: chengc
* @Date: 2020-03-12 13:23
*/
public class TestAgeRule {
@Rule
public AgeRule ageRule = new AgeRule(5);
@Test
public void test1(){
int age = new Random().nextInt(100);
if (age > ageRule.getAge()){
Assert.fail("Beyond the age rule!");
}
}
}
















