关闭

使用Junit4和JMockit进行单元测试

2069人阅读 评论(0) 收藏 举报
分类:
首先介绍下在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");  
    }  
}

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:121297次
    • 积分:1445
    • 等级:
    • 排名:千里之外
    • 原创:137篇
    • 转载:10篇
    • 译文:0篇
    • 评论:28条
    最新评论