您的位置:首页 > 其它

使用Junit4和JMockit进行单元测试

2016-08-11 14:15 169 查看
首先介绍下在Idea中如何安装Juni插件:

1. 安装JUnitGenerator V2.0

在idea中,打开File-Setting-Plugins,在右侧弹出的搜索框中搜索JUnitGenerator V2.0,安装之后重启idea。

2. 设置JUnitGenerator V2.0的属性

在idea中,打开File-Setting-Other Settings-JUnitGenerator

a) 在properties框中,将OutputPath改为  ${SOURCEPATH}/../../test/${PACKAGE}/${FILENAME},将默认template改为Junit4。

b) 在Junit4框中,将package test.$entry.packageName; 改为  package $entry.packageName;

3. 进入想测试的类中,单击鼠标右键-Generator-junit4,能生成你要的测试类,具体的细节可以自己调整。

接下来,看下使用maven的工程如何来编写单元测试代码.主要介绍JUnit,JMockit,Spring-test以及groboutils-core框架

使用Junit4+JMockit进行单元测试的依赖如下:
<!-- https://mvnrepository.com/artifact/junit/junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
</dependency>
<dependency>
  <groupId>org.jmockit</groupId>
  <artifactId>jmockit</artifactId>
  <version>1.21</version>
</dependency>


JMockit有两种测试方式,一种是基于行为的,一种是基于状态的测试。

通俗点讲,基于行为的mock,就是对mock目标代码的行为进行模仿,更像黑盒测试。基于状态的mock,是站在目标测试代码内部的。可以对传入的参数进行检查、匹配,才返回某些结果,类似白盒。

使用JMockit构建单元测试的例子如下:

基于行为的mock:
@RunWith(JMockit.class)
public class ServiceBehavier {

@Mocked
DAO dao = new DAO();

private Service service = new Service();

@Test
public void test() {

// 1. record 录制期望值
new Expectations() {
{
dao.getStoreCount(anyString);// mock这个方法,无论传入任何String类型的值,都返回同样的值,达到黑盒的效果
/**
* 预期结果,返回900
*/
result = 900;
/**
times能且只能调用1次。
*/
times = 1;
}
};
service.setDao(dao);

// 2. replay 调用
Assert.assertEquals(Status.NORMAL, service.checkStatus("D"));

//3.校验是否只调用了一次。如果上面注释的语句再调一次,且把录制的times改为2,那么在验证阶段将会报错。
new Verifications() {
{
dao.getStoreCount(anyString);
times = 1;
}
};

}
}


基于状态的mock:
public class ServiceState {
private DAO dao;
private Service service;
@Test
public void test() {
//1. mock对象
MockUp<DAO> mockUp = new MockUp<DAO>() {
@Mock
public int getStoreCount(String group) {
return 2000;
}
};

//2. 获取实例
dao = mockUp.getMockInstance();
service = new Service();
service.setDao(dao);

//3.调用
Assert.assertEquals(Status.SELLINGWELL, service.checkStatus("FFF"));

//4. 还原对象,避免测试方法之间互相影响。其实对一个实例来说没什么影响,对静态方法影响较大。旧版本的tearDown()方法是Mockit类的静态方法
mockUp.tearDown();
}
}


package com.khlin.test.junit.jmockit.demo;

import mockit.Deencapsulation;
import mockit.Expectations;
import mockit.Injectable;
import mockit.Mock;
import mockit.MockUp;
import mockit.Mocked;
import mockit.NonStrictExpectations;
import mockit.Tested;
import mockit.Verifications;
import mockit.integration.junit4.JMockit;

import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;

import com.khlin.test.junit.jmockit.demo.jmockit.AbstractA;
import com.khlin.test.junit.jmockit.demo.jmockit.ClassA;
import com.khlin.test.junit.jmockit.demo.jmockit.ClassB;
import com.khlin.test.junit.jmockit.demo.jmockit.InterfaceB;

@RunWith(JMockit.class)
public class JMockitTest {

/**
* mock私有方法
*/
@Test
public void testPrivateMethod() {

final ClassA a = new ClassA();
// 局部参数,把a传进去
new Expectations(a) {
{
Deencapsulation.invoke(a, "getAnythingPrivate");
result = 100;
times = 1;
}
};

Assert.assertEquals(100, a.getAnything());

new Verifications() {
{
Deencapsulation.invoke(a, "getAnythingPrivate");
times = 1;
}
};
}

/**
* mock私有静态方法
*/
@Test
public void testPrivateStaticMethod() {

new Expectations(ClassA.class) {
{
Deencapsulation
.invoke(ClassA.class, "getStaticAnythingPrivate");
result = 100;
times = 1;
}
};

Assert.assertEquals(100, ClassA.getStaticAnything());

new Verifications() {
{
Deencapsulation
.invoke(ClassA.class, "getStaticAnythingPrivate");
times = 1;
}
};

}

/**
* mock公有方法
*/
@Test
public void testPublicMethod() {
final ClassA classA = new ClassA();
new Expectations(classA) {
{
classA.getAnything();
result = 100;
times = 1;
}
};

Assert.assertEquals(100, classA.getAnything());

new Verifications() {
{
classA.getAnything();
times = 1;
}
};
}

/**
* mock公有静态方法--基于行为
*/
@Test
public void testPublicStaticMethod() {

new Expectations(ClassA.class) {
{
ClassA.getStaticAnything();
result = 100;
times = 1;
}
};

Assert.assertEquals(100, ClassA.getStaticAnything());

new Verifications() {
{
ClassA.getStaticAnything();
times = 1;
}
};
}

/**
* mock公有静态方法--基于状态
*/
@Test
public void testPublicStaticMethodBaseOnStatus() {

MockUp<ClassA> mockUp = new MockUp<ClassA>() {
@Mock
public int getStaticAnything() { //注意这里不用声明为static
return 100;
}
};

Assert.assertEquals(100, ClassA.getStaticAnything());
}

/**
* mock接口--基于状态
*/
@Test
public void testInterface() {

InterfaceB interfaceB = new MockUp<InterfaceB>() {
@Mock
public int getAnything() {
return 100;
}
}.getMockInstance();

ClassA classA = new ClassA();
classA.setInterfaceB(interfaceB);

Assert.assertEquals(100, classA.getClassBAnything());
}

/**
* mock接口
*/
@Test
public void testInterfaceBasedOnStatus() {
final InterfaceB interfaceB = new ClassB();

new Expectations(interfaceB) {
{
interfaceB.getAnything();
result = 100;
times = 1;
}
};

ClassA classA = new ClassA();
classA.setInterfaceB(interfaceB);

Assert.assertEquals(100, classA.getClassBAnything());

new Verifications() {
{
interfaceB.getAnything();
times = 1;
}
};
}

/**
* mock抽象类
*/
@Test
public void testAbstract() {
AbstractA abstractA = new MockUp<AbstractA>() {
@Mock
public int getAbstractAnything(){
return 100;
}

@Mock
public int getAnything(){
return 1000;
}
}.getMockInstance();

Assert.assertEquals(100, abstractA.getAbstractAnything());

Assert.assertEquals(1000, abstractA.getAnything());
}
}


代码转自博客http://www.cnblogs.com/SirSmith/p/5116802.html

使用spring构建单元测试的依赖如下:
<!-- https://mvnrepository.com/artifact/org.springframework/spring-test -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>4.1.6.RELEASE</version>
<!--注意版本与你的spring框架一致-->
</dependency>


使用spring测试框架加载配置文件的例子如下:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({"classpath:applicationContext.xml"})
public class ReadDaoImplTest {
@Resource ReadDao readDao;

@Test
public void getListTest(){
List<Client> clientList = readDao.getList("client.test", null);

for(Client c:clientList){
System.out.println(c.getVersionNum());
}
}
}


当然,也可以手动加载:
public class ReadDaoImplTest {

public  static void main(String[] args){
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");

context.start();

ReadDao fqaService = (ReadDao) context.getBean("readDao");
System.out.println(fqaService);
}

}


使用groboutils构建单元测试的依赖如下:
<!--并发测试-->
<dependency>
<groupId>net.sourceforge.groboutils</groupId>
<artifactId>groboutils-core</artifactId>
<version>5</version>
</dependency>


使用groboutils构建单元测试的例子如下:
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import java.util.Set;

import net.sourceforge.groboutils.junit.v1.MultiThreadedTestRunner;
import net.sourceforge.groboutils.junit.v1.TestRunnable;

import org.junit.Test;

public class MutiThreadTest {

static String[] path = new String[] { "" };
static Map<String, String> countMap = new Hashtable<String, String>();
static Map<String, String> countMap2 = new Hashtable<String, String>();
static Set<String> countSet = new HashSet<String>();
static List<String> list = new ArrayList<String>();

@Test
public void testThreadJunit() throws Throwable {
//Runner数组,想当于并发多少个。
TestRunnable[] trs = new TestRunnable [10];
for(int i=0;i<10;i++){
trs[i]=new ThreadA();
}

// 用于执行多线程测试用例的Runner,将前面定义的单个Runner组成的数组传入
MultiThreadedTestRunner mttr = new MultiThreadedTestRunner(trs);

// 开发并发执行数组里定义的内容
mttr.runTestRunnables();

}

private class ThreadA extends TestRunnable {
@Override
public void runTest() throws Throwable {
// 测试内容
myCommMethod2();
}
}

public void myCommMethod2() throws Exception {
System.out.println("===" + Thread.currentThread().getId() + "begin to execute myCommMethod2");
for (int i = 0; i <10; i++) {
int a  = i*5;
System.out.println(a);
}
System.out.println("===" + Thread.currentThread().getId() + "end to execute myCommMethod2");
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: