llt

送分小仙女□ 提交于 2019-12-05 22:11:34

Junit
使用方法
在需要测试的方法上加@Test注解即可

import static org.junit.jupiter.api.Assertions.assertEquals;

import org.junit.jupiter.api.Test;

class FirstJUnit5Tests {

@Test
void myFirstTest() {
assertEquals(2, 1 + 1);
}
}
注解
注解 描述
@Test 表示方法是测试方法。与JUnit4的@Test注解不同的是,这个注解没有声明任何属性,因为JUnit Jupiter中的测试扩展是基于他们自己的专用注解来操作的。除非被覆盖,否则这些方法可以继承。
@ParameterizedTest 表示方法是参数化测试。 除非被覆盖,否则这些方法可以继承。
@RepeatedTest 表示方法是用于重复测试的测试模板。除非被覆盖,否则这些方法可以继承。
@TestFactory 表示方法是用于动态测试的测试工厂。除非被覆盖,否则这些方法可以继承。
@TestInstance 用于为被注解的测试类配置测试实例生命周期。 这个注解可以继承。
@TestTemplate 表示方法是测试用例的模板,设计为被调用多次,调用次数取决于自注册的提供者返回的调用上下文。除非被覆盖,否则这些方法可以继承。
@DisplayName 声明测试类或测试方法的自定义显示名称。这个注解不被继承。
@BeforeEach 表示被注解的方法应在当前类的每个@Test,@RepeatedTest,@ParameterizedTest或@TestFactory方法之前执行; 类似于JUnit 4的@Before。 除非被覆盖,否则这些方法可以继承。
@AfterEach 表示被注解的方法应在当前类的每个@Test,@RepeatedTest,@ParameterizedTest或@TestFactory方法之后执行; 类似于JUnit 4的@After。 除非被覆盖,否则这些方法可以继承。
@BeforeAll 表示被注解的方法应该在当前类的所有@Test,@RepeatedTest,@ParameterizedTest和@TestFactory方法之前执行; 类似于JUnit 4的@BeforeClass。 这样的方法可以继承(除非被隐藏或覆盖),并且必须是静态的(除非使用“per-class”测试实例生命周期)。
@AfterAll 表示被注解的方法应该在当前类的所有@Test,@RepeatedTest,@ParameterizedTest和@TestFactory方法之后执行; 类似于JUnit 4的@AfterClass。 这样的方法可以继承(除非被隐藏或覆盖),并且必须是静态的(除非使用“per-class”测试实例生命周期)。
@Nested 表示被注解的类是一个嵌套的非静态测试类。除非使用“per-class”测试实例生命周期,否则@BeforeAll和@AfterAll方法不能直接在@Nested测试类中使用。 这个注解不能继承。
@Tag 在类或方法级别声明标签,用于过滤测试; 类似于TestNG中的test group或JUnit 4中的Categories。这个注释可以在类级别上继承,但不能在方法级别上继承。
@Disabled 用于禁用测试类或测试方法; 类似于JUnit4的@Ignore。这个注解不能继承。
@ExtendWith 用于注册自定义扩展。 这个注解可以继承。
eg:

import static org.junit.jupiter.api.Assertions.fail;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
class StandardTests {
@BeforeAll
static void initAll() {
}
@BeforeEach
void init() {
}
@Test
void succeedingTest() {
}
@Test
void failingTest() {
fail("a failing test");
}
@Test
@Disabled("for demonstration purposes")
void skippedTest() {
// not executed
}
@AfterEach
void tearDown() {
}
@AfterAll
static void tearDownAll() {
}
}
断言
package com.yiibai.junit;
import static org.junit.Assert.*;
import org.junit.Test;
public class AssertionsTest {
@Test
public void test() {
String obj1 = "junit";
String obj2 = "junit";
String obj3 = "test";
String obj4 = "test";
String obj5 = null;
int var1 = 1;
int var2 = 2;
int[] arithmetic1 = { 1, 2, 3 };
int[] arithmetic2 = { 1, 2, 3 };
assertEquals(obj1, obj2);
assertSame(obj3, obj4);
assertNotSame(obj2, obj4);
assertNotNull(obj1);
assertNull(obj5);
assertTrue(var1 var2);
assertArrayEquals(arithmetic1, arithmetic2);
}
}//原文出自【易百教程】,商业转载请联系作者获得授权,非商业请保留原文链接:https://www.yiibai.com/junit/junit-assertions.html
Jmockit
基本使用
JMockit是一款Java类/接口/对象的Mock工具.

Java Mock工具很多,比如easyMock,Mockito等等。为什么要选择JMockit呢?其实也没有啥特别原因,Mock工具的原理都差不多,就看Mock工具封装的API是否易用了。JMockit的API易用,丰富! 写出来的Mock程序代码完全面向对象.

//一个简单的类,能用不同语言打招呼

public class HelloJMockit {
// 向JMockit打招呼
public String sayHello() {
Locale locale = Locale.getDefault();
if (locale.equals(Locale.CHINA)) {
// 在中国,就说中文
return "你好,JMockit!";
} else {
// 在其它国家,就说英文
return "Hello,JMockit!";
}
}
}
//HelloJMockit类的测试类

public class HelloJMockitTest {
/**
* 测试场景:当前是在中国
*/
@Test
public void testSayHelloAtChina() {
// 假设当前位置是在中国
new Expectations(Locale.class) {
{
Locale.getDefault();
result = Locale.CHINA;
}
};
// 断言说中文
Assert.assertTrue("你好,JMockit!".equals((new HelloJMockit()).sayHello()));
}
/**
* 测试场景:当前是在美国
*/
@Test
public void testSayHelloAtUS() {
// 假设当前位置是在美国
new Expectations(Locale.class) {
{
Locale.getDefault();
result = Locale.US;
}
};
// 断言说英文
Assert.assertTrue("Hello,JMockit!".equals((new HelloJMockit()).sayHello()));
}
}
在上面的例子中,为了对依赖(当前的位置)进行Mock,用简单的3行代码即可搞定。把测试代码的依赖抽象成期待(Expectations),并把期待类Expectations作为本测试程序的内部类,可以任意访问本测试程序类的所有成员,为编写Mock程序提供极大便利。API面向对象特性封装良好。

此外,JMockit还提供了注解,支持泛型的Mock API用于对类/对象的属性,方法(支持static,private,final,native),构造函数,初始代码块(含静态初始代码块)灵活Mock。

jmockit常用api
@Mocked
当@Mocked修饰一个类时

//@Mocked注解用途
public class MockedClassTest {
// 加上了JMockit的API @Mocked, JMockit会帮我们实例化这个对象,不用担心它为null
@Mocked
Locale locale;
// 当@Mocked作用于class
@Test
public void testMockedClass() {
// 静态方法不起作用了,返回了null
Assert.assertTrue(Locale.getDefault() == null);
// 非静态方法(返回类型为String)也不起作用了,返回了null
Assert.assertTrue(locale.getCountry() == null);
// 自已new一个,也同样如此,方法都被mock了
Locale chinaLocale = new Locale("zh", "CN");
Assert.assertTrue(chinaLocale.getCountry() == null);
}
}
当@Mocked修饰一个接口/抽象类时

//@Mocked注解用途
public class MockedInterfaceTest {
// 加上了JMockit的API @Mocked, JMockit会帮我们实例化这个对象,尽管这个对象的类型是一个接口,不用担心它为null
@Mocked
HttpSession session;
// 当@Mocked作用于interface
@Test
public void testMockedInterface() {
// (返回类型为String)也不起作用了,返回了null
Assert.assertTrue(session.getId() == null);
// (返回类型为原始类型)也不起作用了,返回了0
Assert.assertTrue(session.getCreationTime() == 0L);
// (返回类型为原非始类型,非String,返回的对象不为空,这个对象也是JMockit帮你实例化的,同样这个实例化的对象也是一个Mocked对象)
Assert.assertTrue(session.getServletContext() != null);
// Mocked对象返回的Mocked对象,(返回类型为String)的方法也不起作用了,返回了null
Assert.assertTrue(session.getServletContext().getContextPath() == null);
}
}
@Mocked功能总结

通过上述例子,可以看出:@Mocked修饰的类/接口,是告诉JMockit,帮我生成一个Mocked对象,这个对象方法(包含静态方法)返回默认值。
即如果返回类型为原始类型(short,int,float,double,long)就返回0,如果返回类型为String就返回null,如果返回类型是其它引用类型,则返回这个引用类型的Mocked对象。

Expectations
Expectations主要有两种使用方式。

通过引用外部类的Mock对象(@Injectabe,@Mocked,@Capturing)来录制

//Expectations对外部类的mock对象进行录制
public class ExpectationsTest {
@Mocked
Calendar cal;
@Test
public void testRecordOutside() {
new Expectations() {
{
// 对cal.get方法进行录制,并匹配参数 Calendar.YEAR
cal.get(Calendar.YEAR);
result = 2016;// 年份不再返回当前小时。而是返回2016年
// 对cal.get方法进行录制,并匹配参数 Calendar.HOUR_OF_DAY
cal.get(Calendar.HOUR_OF_DAY);
result = 7;// 小时不再返回当前小时。而是返回早上7点钟
}
};
Assert.assertTrue(cal.get(Calendar.YEAR) == 2016);
Assert.assertTrue(cal.get(Calendar.HOUR_OF_DAY) == 7);
// 因为没有录制过,所以这里月份返回默认值 0
Assert.assertTrue(cal.get(Calendar.DAY_OF_MONTH) == 0);
}
}
在这个例子中,在Expectations匿名内部类的初始代码块中,我们可以对外部类的任意成员变量,方法进行调用。大大便利我们书写录制脚本。

通过构建函数注入类/对象来录制

在上面的例子中,我们通过引用外部类的Mock对象(@Injectabe,@Mocked,@Capturing)来录制,可是无论是@Injectabe,@Mocked,@Capturing哪种Mock对象,都是对类的方法都mock了,可是有时候,我们只希望JMockit只mock类/对象的某一个方法。怎么办? 看下面的例子就明白啦。

//通过Expectations对其构造函数mock对象进行录制
public class ExpectationsConstructorTest2 {
// 把类传入Expectations的构造函数
@Test
public void testRecordConstrutctor1() {
Calendar cal = Calendar.getInstance();
// 把待Mock的类传入Expectations的构造函数,可以达到只mock类的部分行为的目的
new Expectations(Calendar.class) {
{
// 只对get方法并且参数为Calendar.HOUR_OF_DAY进行录制
cal.get(Calendar.HOUR_OF_DAY);
result = 7;// 小时永远返回早上7点钟
}
};
Calendar now = Calendar.getInstance();
// 因为下面的调用mock过了,小时永远返回7点钟了
Assert.assertTrue(now.get(Calendar.HOUR_OF_DAY) == 7);
// 因为下面的调用没有mock过,所以方法的行为不受mock影响,
Assert.assertTrue(now.get(Calendar.DAY_OF_MONTH) == (new Date()).getDate());
}
// 把对象传入Expectations的构造函数
@Test
public void testRecordConstrutctor2() {
Calendar cal = Calendar.getInstance();
// 把待Mock的对象传入Expectations的构造函数,可以达到只mock类的部分行为的目的,但只对这个对象影响
new Expectations(cal) {
{
// 只对get方法并且参数为Calendar.HOUR_OF_DAY进行录制
cal.get(Calendar.HOUR_OF_DAY);
result = 7;// 小时永远返回早上7点钟
}
};
// 因为下面的调用mock过了,小时永远返回7点钟了
Assert.assertTrue(cal.get(Calendar.HOUR_OF_DAY) == 7);
// 因为下面的调用没有mock过,所以方法的行为不受mock影响,
Assert.assertTrue(cal.get(Calendar.DAY_OF_MONTH) == (new Date()).getDate());
// now是另一个对象,上面录制只对cal对象的影响,所以now的方法行为没有任何变化
Calendar now = Calendar.getInstance();
// 不受mock影响
Assert.assertTrue(now.get(Calendar.HOUR_OF_DAY) == (new Date()).getHours());
// 不受mock影响
Assert.assertTrue(now.get(Calendar.DAY_OF_MONTH) == (new Date()).getDate());
}
}
MockUp & Mock
MockUp & @Mock提供的Mock方式
MockUp是使用最多的方法,该方式简单直接,可以清楚看到具体mock的类和方法
对于private和static方法,也可以使用MockUp,只需要去掉static关键字或者将private修改为public,再加上@Mock注解即可。

//Mockup & @Mock的Mock方式
public class MockUpTest {
@Test
public void testMockUp() {
// 对Java自带类Calendar的get方法进行定制
// 只需要把Calendar类传入MockUp类的构造函数即可
new MockUp(Calendar.class) {
// 想Mock哪个方法,就给哪个方法加上@Mock, 没有@Mock的方法,不受影响
@Mock
public int get(int unit) {
if (unit == Calendar.YEAR) {
return 2017;
}
if (unit == Calendar.MONDAY) {
return 12;
}
if (unit == Calendar.DAY_OF_MONTH) {
return 25;
}
if (unit == Calendar.HOUR_OF_DAY) {
return 7;
}
return 0;
}
};
// 从此Calendar的get方法,就沿用你定制过的逻辑,而不是它原先的逻辑。
Calendar cal = Calendar.getInstance(Locale.FRANCE);
Assert.assertTrue(cal.get(Calendar.YEAR) == 2017);
Assert.assertTrue(cal.get(Calendar.MONDAY) == 12);
Assert.assertTrue(cal.get(Calendar.DAY_OF_MONTH) == 25);
Assert.assertTrue(cal.get(Calendar.HOUR_OF_DAY) == 7);
// Calendar的其它方法,不受影响
Assert.assertTrue((cal.getFirstDayOfWeek() == Calendar.MONDAY));
}
}

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!