栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

单元测试之道java版:使用junit百度云(单元测试之后应该进行)

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

单元测试之道java版:使用junit百度云(单元测试之后应该进行)

一、简介

EasyMock、Mockito、jMock(单元测试模拟框架)
在有这些模拟框架之前,程序员为了编写某一个函数的单元测试,必须进行十分繁琐的初始化工作,以确保调用的接口或编写的代码得到预期的结果。单元测试模拟框架极大的简化了单元测试的编写过程,在被测试代码需要调用某些接口的时候,直接模拟一个假的接口,并任意指定该接口的行为。这样就可以大大的提高单元测试的效率以及单元测试代码的可读性。
**缺点:**都不可以实现对静态函数、构造函数、私有函数、Final函数以及系统函数的模拟,但是这些方法往往是我们在大型系统中需要的功能Power Mock
PowerMock 是在EasyMock以及Mockito基础上的扩展,通过定制类加载等技术,PowerMock实现了之前提到的所有模拟功能,使其成为大型系统上单元测试中的必备工具。Mock
Mock的意思是模拟,就是模拟接口返回的信息,用已有的信息替换它需要返回的信息,从而实现对上级模块的测试、 二、依赖


        1.6.6


		
			    org.powermock
			    powermock-module-junit4
			    ${powermock.version}
			    test
		
		
			    org.powermock
			    powermock-api-mockito
			    ${powermock.version}
			    test
		

三、相关注解
@RunWith(PowerMockRunner.class)
@PrepareForTest({UserController.class, CommonUtils.class})
@PowerMockIgnore("javax.management.*")
public class UserController {
    @Mock
    private UserService userService;
    @InjectMocks
    private  UserController userController = new UserController();
}

@RunWith(PowerMockRunner.class)
表明用PowerMockerRunner来测试用例,否则无法使用PowerMock@PrepareForTest({UserController.class, CommonUtils.class})
所有需要测试的类,列在此处,以逗号分隔;在运行测试用例时,会创建一个新的org.powermock.core.classloader.MockClassLoader实例,然后加载该测试用例使用到的类@PowerMockIgnore(“javax.management.*”)
为了解决使用powermock后,提示classloader错误@Mock
注解修饰会mock出来一个userService对象@InjectMocks
注解会主动将已存在的mock对象注入到bean中,按名称注入,这个注解修饰在我们需要测试的类上。必须要手动new一个实例,不然单元测试会有问题。 四、使用(示例代码在文末)

PowerMockito.mock():
指定需要mock的类型类(接口或者实现类),生成Mock类,其中所有的方法都不是真实的方法,访问对象方法不会执行具体逻辑,而且返回值都是NULL或者Empty。
使用打桩返回给定数据:PowerMockito.when().thenReturn()方法
若要执行具体逻辑:PowerMockito.when().thenCallRealMethod()方法PowerMockito.spy():
spy机制可以监视一个真实对象,对其进行方法调用会执行真实逻辑;
spy也可以打桩指定的方法。
spy中使用都Return…when打桩,不会执行具体逻辑
spy中使用when…thenReturn打桩,会执行具体逻辑mock有返回值的普通方法

@Test
 public void test_addUser(){
     User user = new User();
     PowerMockito.when(userService.addUser(user)).thenReturn(1);
     boolean result = userController.addUser(user);
     Assert.assertEquals(result, true);
 }

注:userService.addUser()和userController.addUser()所使用的参数值必须保持一致

mock无返回值的普通方法
方法一:

 @Test
 public void test_initUser() throws Exception {
     User user = new User();
     user.setId(111);
     PowerMockito.donothing().when(userService, "initUser", user);
     User result = userController.initUser(user);
     Assert.assertEquals(result.getId(), 111);
 }

方法二:

@Test
public void test_initUser1() throws Exception {
    User user = new User();
    user.setId(111);
    PowerMockito.donothing().when(userService).initUser(user);
    User result = userController.initUser(user);
    Assert.assertEquals(result.getId(), 111);
}

mock抛异常

@Test
public void test_delUser() throws Exception {
    PowerMockito.when(userService.delUser(1)).thenThrow(new Exception("删除失败"));
    boolean result = userController.delUser(1);
    Assert.assertEquals(result, false);
}

注:thenThrow()中抛出delUser()方法抛出的异常或其子异常

mock静态方法

@Test
public void test_append() {
     PowerMockito.mockStatic(CommonUtils.class);
     PowerMockito.when(CommonUtils.isNotEmpty("World")).thenReturn(false);
     String result = userController.append("World");
     Assert.assertEquals(result, "Hello");
 }

注:需要在@PrepareForTest注解中加上CommonUtils.class

mock返回值为void的static方法
方法一:

@Test
public void test_getFile() throws Exception {
   String filePath = "xiaofeng";
    PowerMockito.mockStatic(CommonUtils.class);
    PowerMockito.donothing().when(CommonUtils.class, "validFilePath", filePath);
    File result = userController.getFile(filePath);
    Assert.assertEquals(result.getName(), filePath);
}

方法二:

@Test
public void test_getFile1() throws Exception {
    String filePath = "xiaofeng";
    PowerMockito.mockStatic(CommonUtils.class);
    PowerMockito.donothing().when(CommonUtils.class);
    CommonUtils.validFilePath(filePath);
    File result = userController.getFile(filePath);
    Assert.assertEquals(result.getName(), filePath);
}

mock私有方法
方法一:

@Test
public void test_modUser() throws Exception {
   User user = new User();
    PowerMockito.when(userService.modUser(user)).thenReturn(1);
    UserController controller = PowerMockito.mock(UserController.class);
    // 给没有set方法的私有属性赋值
    Whitebox.setInternalState(controller, "userService", userService);
    // 因为要测试的是modUser()方法,所以调用这个方法时,应调用真实方法,并非mock掉的方法
    PowerMockito.when(controller.modUser(user)).thenCallRealMethod();
    // 在modUser()方法中会调用verifyMod()这个私有方法,所以将其mock掉
    PowerMockito.when(controller, "verifyMod", 1).thenReturn(false);
    boolean result = controller.modUser(user);
    Assert.assertEquals(result, false);
}

注:此处的controller是mock出来的,不是UserControllerTest类中的成员变量userController(不会执行verifyMod方法,直接返回模拟值)
方法二:

@Test
public void test_modUser1() throws Exception {
    User user = new User();
    PowerMockito.when(userService.modUser(user)).thenReturn(1);
    // 对userController进行监视
    UserController controller = PowerMockito.spy(userController);
    // 当userController的verifyMod被执行时,将被mock掉
    PowerMockito.when(controller, "verifyMod", 1).thenReturn(false);
    boolean result = controller.modUser(user);
    Assert.assertEquals(result, false);
}

注:spy方法可以避免执行被测类中的成员函数,即mock掉不想被执行的私有方法(会执行verifyMod方法,但是会返回模拟值)

测试私有方法(注意:是测试,不是mock)
方法一:

@Test
public void test_verifyMod() throws Exception {
   // 获取method方法
    Method method = PowerMockito.method(UserController.class, "verifyMod", Integer.class);
    // 调用Method的invoke方法来执行
    boolean result = (boolean) method.invoke(userController, 1);
    Assert.assertEquals(result, true);
}

方法二:

@Test
public void test_verifyMod1() throws Exception {
   // 直接通过Whitebox来执行
    boolean result = Whitebox.invokeMethod(userController, "verifyMod", 1);
    Assert.assertEquals(result, true);
}

mock新建对象

@Test
public void test_getUser() throws Exception {
   User user = new User();
    user.setName("大风");
    PowerMockito.whenNew(User.class).withNoArguments().thenReturn(user);
    User result = userController.getUser();
    Assert.assertEquals(result.getName(), "大风");
}

mock同一方法,返回不同的值

@Test
public void test_getString() throws Exception {
    UserController controller = PowerMockito.spy(userController);
    PowerMockito.when(controller, "getFlag").thenReturn(true, false);
    String result = controller.getString("Hello");
    Assert.assertEquals(result, "Hello");
}

mock final方法
final与普通方法一样mock,但是需要将其所在class添加到@PrepareForTest注解中参数的模糊匹配
org.mockito.Matchers类中,提供了很多any*的方法,如anyObject()、anyString()…我们可以使用这些方法去避免构建那些难以模拟的输入参数
注:如果对某一个参数使用了Matcher,那么这个方法的所有其它参数也必须使用Matcher,否则将会报错。 五、示例代码

package com.example.pattren.junitTest;

public class User {
    private int id;
    private String name;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
package com.example.pattren.junitTest;

public interface UserService {
    int addUser(User user);

    void initUser(User user);

    int delUser(int id) throws Exception;

    int modUser(User user);
}
package com.example.pattren.junitTest;

import java.io.File;
import java.io.IOException;
import java.net.URLDecoder;
import java.text.Normalizer;

public class CommonUtils {
    public static boolean isEmpty(CharSequence cs) {
        return cs == null || cs.length() == 0;
    }

    public static boolean isNotEmpty(CharSequence cs) {
        return !isEmpty(cs);
    }

    public static void validFilePath(String filePath) throws IOException {
        if (CommonUtils.isEmpty(filePath)) {
            throw new IOException("the file path is empty");
        }
        filePath = Normalizer.normalize(filePath, Normalizer.Form.NFKC);
        File file = new File(filePath);
        String decode = URLDecoder.decode(file.getCanonicalPath(), "UTF-8");
        file = new File(decode);
        if (!file.exists()) {
            throw new IOException("the file path is not exists");
        }
    }
}
package com.example.pattren.junitTest;

import java.io.File;
import java.io.IOException;

public class UserController {
    private UserService userService;

    public boolean addUser(User user) {
        int i = userService.addUser(user);
        if (i <= 0) {
            return false;
        } else {
            return true;
        }
    }

    public User initUser(User user) {
        userService.initUser(user);
        return user;
    }

    public boolean delUser(int id) {
        try {
            userService.delUser(id);
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    public String append(String param) {
        String str = "Hello";
        if (CommonUtils.isNotEmpty(param)) {
            return str + param;
        } else {
            return str;
        }
    }

    public File getFile(String filePath) throws IOException {
        CommonUtils.validFilePath(filePath);
        return new File(filePath);
    }

    public boolean modUser(User user) {
        int flag = userService.modUser(user);
        return verifyMod(flag);
    }

    private boolean verifyMod(Integer flag) {
        if (flag > 0) {
            return true;
        }
        return false;
    }

    public User getUser() {
        User user = new User();
        return user;
    }

    public String getString(String str) {
        StringBuffer result = new StringBuffer();
        while (this.getFlag()) {
            result.append(str);
        }
        return result.toString();
    }

    private boolean getFlag() {
        return true;
    }
}
package com.example.pattren.junitTest;

import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PowerMockIgnore;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import org.powermock.reflect.Whitebox;

import java.io.File;
import java.lang.reflect.Method;

@RunWith(PowerMockRunner.class)
@PrepareForTest({UserController.class, CommonUtils.class})
@PowerMockIgnore("javax.management.*")
public class UserControllerTest {
    @Mock
    private UserService userService;
    @InjectMocks
    private UserController userController = new UserController();

    
    @Test
    public void test_addUser() {
        User user = new User();
        PowerMockito.when(userService.addUser(user)).thenReturn(1);
        boolean result = userController.addUser(user);
        Assert.assertEquals(result, true);
    }

    
    @Test
    public void test_initUser() throws Exception {
        User user = new User();
        user.setId(111);
        PowerMockito.donothing().when(userService, "initUser", user);
        User result = userController.initUser(user);
        Assert.assertEquals(result.getId(), 111);
    }

    
    @Test
    public void test_initUser1() throws Exception {
        User user = new User();
        user.setId(111);
        PowerMockito.donothing().when(userService).initUser(user);
        User result = userController.initUser(user);
        Assert.assertEquals(result.getId(), 111);
    }

    
    @Test
    public void test_delUser() throws Exception {
        PowerMockito.when(userService.delUser(1)).thenThrow(new Exception("删除失败"));
        boolean result = userController.delUser(1);
        Assert.assertEquals(result, false);
    }

    
    @Test
    public void test_append() {
        PowerMockito.mockStatic(CommonUtils.class);
        PowerMockito.when(CommonUtils.isNotEmpty("World")).thenReturn(false);
        String result = userController.append("World");
        Assert.assertEquals(result, "Hello");
    }

    
    @Test
    public void test_getFile() throws Exception {
        String filePath = "xiaofeng";
        PowerMockito.mockStatic(CommonUtils.class);
        PowerMockito.donothing().when(CommonUtils.class, "validFilePath", filePath);
        File result = userController.getFile(filePath);
        Assert.assertEquals(result.getName(), filePath);
    }

    
    @Test
    public void test_getFile1() throws Exception {
        String filePath = "xiaofeng";
        PowerMockito.mockStatic(CommonUtils.class);
        PowerMockito.donothing().when(CommonUtils.class);
        CommonUtils.validFilePath(filePath);
        File result = userController.getFile(filePath);
        Assert.assertEquals(result.getName(), filePath);
    }

    
    @Test
    public void test_modUser() throws Exception {
        User user = new User();
        PowerMockito.when(userService.modUser(user)).thenReturn(1);
        UserController controller = PowerMockito.mock(UserController.class);
        // 给没有set方法的私有属性赋值
        Whitebox.setInternalState(controller, "userService", userService);
        // 因为要测试的是modUser()方法,所以调用这个方法时,应调用真实方法,并非mock掉的方法
        PowerMockito.when(controller.modUser(user)).thenCallRealMethod();
        // 在modUser()方法中会调用verifyMod()这个私有方法,所以将其mock掉
        PowerMockito.when(controller, "verifyMod", 1).thenReturn(false);
        boolean result = controller.modUser(user);
        Assert.assertEquals(result, false);
    }

    
    @Test
    public void test_modUser1() throws Exception {
        User user = new User();
        PowerMockito.when(userService.modUser(user)).thenReturn(1);
        // 对userController进行监视
        UserController controller = PowerMockito.spy(userController);
        // 当userController的verifyMod被执行时,将被mock掉
        PowerMockito.when(controller, "verifyMod", 1).thenReturn(false);
        boolean result = controller.modUser(user);
        Assert.assertEquals(result, false);
    }

    
    @Test
    public void test_verifyMod() throws Exception {
        // 获取method方法
        Method method = PowerMockito.method(UserController.class, "verifyMod", Integer.class);
        // 调用Method的invoke方法来执行
        boolean result = (boolean) method.invoke(userController, 1);
        Assert.assertEquals(result, true);
    }

    
    @Test
    public void test_verifyMod1() throws Exception {
        // 直接通过Whitebox来执行
        boolean result = Whitebox.invokeMethod(userController, "verifyMod", 1);
        Assert.assertEquals(result, true);
    }

    
    @Test
    public void test_getUser() throws Exception {
        User user = new User();
        user.setName("大风");
        PowerMockito.whenNew(User.class).withNoArguments().thenReturn(user);
        User result = userController.getUser();
        Assert.assertEquals(result.getName(), "大风");
    }

    
    @Test
    public void test_getString() throws Exception {
        UserController controller = PowerMockito.spy(userController);
        PowerMockito.when(controller, "getFlag").thenReturn(true, false);
        String result = controller.getString("Hello");
        Assert.assertEquals(result, "Hello");
    }
}
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/773700.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号