单元测试中PowerMock常用方法

在进行单元测试时,为了测试一个简单的方法,往往需要构造一堆复杂的相当对象,还有的情况是有的方法没有返回值,直接在函数内做了某些事情,这时如果用黑盒测试,你无法通过输入输出判断方法是否正确。所以,通常都会通过mock对象的方法来进行unit test. 有机会再总结软件测试一些理论知识,今天先把这几天写unit test中常用的powerMock使用方法写一下(所有例子都是直接在网页内敲出来的,不能直接运行)。
1. mock 一个测试时不方便创建的对象,并设定public方法的预期行为。
例如MediaManager类中的方法:
 public int getSystemVolume()
{

     context.setAudioEnable(true);
    Audio audio = context.getSystemAudio(Context.AUDIO);
    return audio.getStreamVolume();
}

其中的context对象是平台相关的,在测试程序中根本无法创建些Context的对象,在测试时我认为只要程序能去执行平台相关的这个对象的这个方法,这个方法就是正确的。
测试如下
@RunWith(PowerMockRunner.class)
@PrepareForTest(MediaManager.class)
public class MediaManagerTest
{
    private Context context;
    private MediaManager mediaManager;

    @Before
    public void setUp() throws Exception
    {
        context = PowerMock.createMock(Context.class);
        mediaManager = new MediaManager(context);
    }

    @Test
    public void testGetSystemVolume()
    {
        PowerMock.resetAll();
        Audio audio = PowerMock.createMock(Audio.class);

        context.setAudioEnable(true);//Mock对象的方法返回值为void时,这样写表示预期被调用一次
        EasyMock.expect(context.getSystemAudio(Context.AUDIO).andReturn(audio);//表示context对象的getSystemAudio方法将会调用一次,参数是Context.AUDIO,设定它的返回值为audio.
        EasyMock.expect(audio.getStreamVolume()).andReturn(20);//audio的getStreamVolume()方法将会调用一次,设定它的返回值为20
        PowerMock.replayAll(); //录制
      int volume = mediaManager.getSystemVolume();
        PowerMock.verifyAll();//验证上面录制的对象中的方法有没有按预期被调用
      assertEquals(volume, 20); 
    }

}

 2.Mock 静态的方法.

如果对一个Mock对象的静态方法进行预期设定,还需要做一些工作才能实现(1)在PrepareForTest里添加此方法的类名.(2)在Mock静态方法前声明PowerMock.mockStatic(Class.class),如果上例中的Context的setAudioEnable为静态方法,测试程序如下:

@RunWith(PowerMockRunner.class)
@PrepareForTest({MediaManager.class,Context.class})
public class MediaManagerTest
{
    private Context context;
    private MediaManager mediaManager;

    ...............

    @Test
    public void testGetSystemVolume()
    {
        PowerMock.resetAll();

       PowerMock.mockStatic(Context.class);

       Context.setAudioEnable(true);//Mock对象的方法返回值为void时,这样写表示预期被调用一次

        Audio audio = PowerMock.createMock(Audio.class);
        EasyMock.expect(context.getSystemAudio(Context.AUDIO).andReturn(audio);//表示context对象的getSystemAudio方法将会调用一次,参数是Context.AUDIO,设定它的返回值为audio.
        EasyMock.expect(audio.getStreamVolume()).andReturn(20);//audio的getStreamVolume()方法将会调用一次,设定它的返回值为20
        PowerMock.replayAll(); //录制
      int volume = mediaManager.getSystemVolume();
        PowerMock.verifyAll();//验证上面录制的对象中的方法有没有按预期被调用
      assertEquals(volume, 20); 

在有些特殊情况下,如果Context为子类,还需要将其基类名加入到类名的@PrepareForTest中的列表中。

    }

}


 3. Mock  创建新对象 和 参数匹配

如果在你被测试的方法内部有这样两句话


Camera  camera = new Camera( int length);

camera.open("thePath");  // path 是前面已有的某个String类对象

camera.setFileName(new String[ ]{ "id"}, 20);

因为Camera是设备相关的,在测试环境内无法创建此种类型对象,而此时又无法自己Mock一个Camera传进来,所以只能在它 new Camera()时给它替换一个自己Mock的对象,这种情况可以用PowerMock.expectNew()来实现。针对上面代码可以用如下实现Mock:

Camera   camera = PowerMock.createMock(Camera.class); //先Mock出一个用于替换的对象

PowerMock.expectNew(Camera.class, EasyMock.anyInt()).andReturn(camera );

camera.open(EasyMock.anyObject(String.class));  //此处表示检验程序时open()方法中传入的只要是String类对象

                                                                                            //就满足条件,对具体对象不敏感

camera.setFileName(EasyMock.aryEq(new String[]{"id"}), EasyMock.eq(20) );

上面的EasyMock.anyInt()表示无论被测试方法中的new Camera()中实际传的参数是什么值,只要是个Int值,都满足被Mock对象替换掉的条件,使用EasyMock.anyObject(Class.class),可以匹配类类型,这样可以使检验时不用指定严格的参数值。

上面对setFileName()进行mock时,直接new 一个同样的String数组传进去,并不能通过验证,因为数组的内容相等但它的值不相等,所以你传的值和它预期的值不相同,故通不过测试,而EasyMock.aryEq(new String[]{"id"}则可以通过验证,验证时它会验证数组内容而不数组对象本身。需要注意的是如果方法有多个参数,其中一个使用了这种匹配的验证方法,其它的也得使用匹配验证方法。

  • 2
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值