浅谈EasyMock和PowerMock

来源:互联网 发布:星舞卓萌网络直播 编辑:程序博客网 时间:2024/04/24 17:40

晦涩的EasyMock和PowerMock

又到了周末,作为程序的我深感苦逼,周末无地可去。。。本来心想到了周末可以好好放松放松了,可是真心无伴无钱。此时的困境怎一个囧字了得。嘿嘿!前面是我的一番抱怨了。下面,切入正题吧。

经过一周的学习,算是对EasyMock和PowerMock有了一点点了解。由于我们公司的开发人员在进行单元测试的时候需要使用到的,而且作为新来的毕业生菜鸟。我开始学期了EasyMock和PowerMock。首先我们需要了解什么是EasyMock和PowerMock。

EasyMock:可以从其名称上面入手,简单的Mock。其主要是进行Mock一些接口,当我们在项目中需要使用别人的模块的东西的时候,而我们又不知道别人的有关接口的具体实现。但是我们又需要使用与之有关的结果。此时EasyMock便可以很好的扮演mock的角色。我们可以把相关的接口实现通过EasyMock.createMock(接口.class)来模拟其实现类。

          其EasyMock主要有一下几步

                1:模拟一个接口对象:

                      UserDao udao=EasyMock.createMock(UserDao.class)此时Mock对象处于Record状态

                2:设定Mock对象的预期行为和希望得到的结果

                      /**
                        * EasyMock.expect()方法后面必定跟着返回值
                      */
                      EasyMock.expect(udao.getById(1001)).andReturn(expectedUser);

                3:replay()重置mock对象

                       EasyMock.replay(udao)

                4:进行验证

                      EasyMock.verify(udao)

EasyMock的使用核心路线主要是:Record------->Replay---------->verify三种状态的切换

以下附上一个完整的代码:

package com.test;

import junit.framework.Assert;

import org.easymock.EasyMock;
import org.junit.Test;

import com.bean.User;
import com.dao.UserDao;
import com.service.impl.UserServiceImpl;
/**
 * 使用Mock对象模拟测试的时候,equals(),hashcode(),toString()三个函数无法更改其行为
 * @author Clark
 * class mock除了以上三个限制外还有final,private方法都不能被mock
 * 对于静态方法,easymock也无法mock其行为
 */
public class UserServiceImplTest extends Assert{
 @Test
 public void testQuery(){
  User expectedUser=new User(1001,"clark");
  UserDao udao=EasyMock.createMock(UserDao.class);
  /**
   * EasyMock.expect()方法后面必定跟着返回值
   */

//此处的1001相当于数据库中表的别名。。我们可以随便取名,与前面的1001无关系
  EasyMock.expect(udao.getById(1001)).andReturn(expectedUser);
  /**
   * 如果mock对象的方法是void,则需要使用expectLastCall()方法
   */
//  udao.sayHi();
//  EasyMock.expectLastCall();
  
  EasyMock.replay(udao);
  
  UserServiceImpl service=new UserServiceImpl();
  service.setUserDao(udao);
  User u=service.query(1001);
  assertNotNull(u);
  assertEquals(expectedUser,u);


  EasyMock.verify(udao);
 }
}

User类package com.bean;

public class User {
 public int userId;
 public String userName;
 public int getUserId() {
  return userId;
 }
 public void setUserId(int userId) {
  this.userId = userId;
 }
 public String getUserName() {
  return userName;
 }
 public void setUserName(String userName) {
  this.userName = userName;
 }
 public User(int userId, String userName) {
  this.userId = userId;
  this.userName = userName;
 }
 public User() {
 }
}

Mock的UserDao接口

package com.dao;

import com.bean.User;

public interface UserDao {
 public User getById(int userId);
 
 public void sayHi();
}

 

package com.service;

import com.bean.User;

public interface UserService {
 User query(int userId);
}

 

package com.service.impl;

import com.bean.User;
import com.dao.UserDao;
import com.service.UserService;

public class UserServiceImpl implements UserService{
 private UserDao userDao;
 
 public void setUserDao(UserDao userDao) {
  this.userDao = userDao;
 }

 public User query(int userId) {
  
  return userDao.getById(userId);
 }
 public void print(){
  userDao.sayHi();
 }
}
PowerMock是EasyMock的一个扩展,加入了static,final,private,以及constructor的Mock功能。但是PowerMock并没有继承EasyMock的一些测试功能,所以不能取代EasyMock,而单独使用。在很多时候必须要PowerMock和EasyMock相互结合,以及加上WhiteBox,才能更好实现测试。

  1. 必不可少的一步:添加测试运行器@RunWith(PowerMockRunner.class),如果没有添加这个运行器,则使用的是默认的JUnit4.class。在PrepareForTest中加入测试class。@PrepareForTest(测试.class)

        Mock构造器函数

        public class A{
        public void doA(){
          new B();
          }
      }

    public class B{
       public B(){
           System.out.println("can't be here!");
        }
    }
       

    测试classA中的doA方法:

  @RunWith(PowerMockRunner.class)
  @PrepareForTest({A.class})
  public class ATest {

      @Test
      public void testdoA() throws Exception {
          B mockB = PowerMock.createMock( B.class );
          PowerMock.expectNew( B.class ).andReturn(mockB);
          A testA = new A();
          PowerMock.replayAll();
          testA.doA();
          PowerMock.verifyAll();
      }
  }

但是在单元测试testdoA()方法的时候总是会报:

         testdoA()

                 Unrooted Tests

                         initializationError

心里好纳闷,查了好多资料都没解决。希望哪位高手看到了帮小弟解决一下

 3.static

    测试static方法的时候必须要加上@PrepareForTest(静态方法.class),否则就会抛出java.lang.IllegalStateException: no last call on a mock available异常。如果有多个class,用{},例如@PrepareForTest({A.class,B.class})

    public class A{
        public void doA(){
          B.doB();
        }
    }

    public class B{
        public static String doB() {
          return ("can't be here !");
        }
    }

    测试classA中的doA方法:

    @RunWith(PowerMockRunner.class)
    @PrepareForTest({A.class, B.class})
    public class ATest {
        @Test
        public void testdoA() throws Exception {
            PowerMock.mockStatic( B.class );
            EasyMock.expect(B.doB()).andReturn("Mocked !");
            A testA = new A();
            PowerMock.replayAll();
            assertEquals("Mock not complete !", testA.doA(), "Mocked !");
            PowerMock.verifyAll();
        }
    }

  4.mock类中的Field

    一个好的Field应该有getter和setter,但是代码中没有,我们也可以用WhiteBox来Mock掉Field。

    public class A{
        private String C;

        public A(){
            C = "Can't be here !";
        }
   
        public String doA(){
            return C;
        }
   
    }

    测试A中的doA方法

    @RunWith(PowerMockRunner.class)
    @PrepareForTest({A.class, B.class})
    public class ATest {

        @Test
        public void testdoA(){
            A testA = new A();
            String mockC = "Mocked !";
            Whitebox.setInternalState( testA, "C", mockC );
            assertEquals("Mock not complete !", testA.doA(), "Mocked !");
        }

    }

原创粉丝点击