用powermock mock Dao Http请求 log4j

junit中比较常用的三种情形:
1.mock log4j,对log进行测试
2.mock DAO,使得测试脱离真实的DB环境,不需要连数据库
3.mock Http,使得测试脱离外部环境,不需要真的去进行Http请求


package com.project.service;

import com.project.bean.User;
import com.project.dao.UserDAO;
import com.project.mock.MockLog;

import org.apache.commons.logging.LogFactory;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.StatusLine;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.impl.client.DefaultHttpClient;
import org.easymock.EasyMock;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.easymock.PowerMock;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;

@RunWith(PowerMockRunner.class)
@PrepareForTest({TargetService.class, LogFactory.class, DefaultHttpClient.class}) // 告诉PowerMock哪些类需要被mock
public class TargetServiceTest {

private MockLog mLog;

@Before
public void setUp() {

// 实例化自己的mock log对象
mLog = new MockLog();
// 通过反射对TargetService中的变量log进行mock
Whitebox.setInternalState(TargetService.class, "log", mLog);
}

/**
* mock log4j示例
* @throws Exception
*/
@Test
public void testLog4j() throws Exception {
// mock
TargetService target = PowerMock.createPartialMock(TargetService.class, "method1");
PowerMock.expectPrivate(target, "method1").andThrow(new IOException());
PowerMock.replay(target);

// 验证是否抛出IOException
Assert.assertEquals(IOException.class , mLog.getExceptionList().get(0).getClass());
// 验证log的条数是否正确
Assert.assertEquals(1, mLog.getLogList().size());
// 验证log输出的错误信息是否正确
Assert.assertEquals("system error" , mLog.getLogList().get(0));

PowerMock.verify(target);
}

/**
* mock DAO,使得测试脱离真实的DB环境,不需要连数据库
* @throws Exception
*/
@Test
public void testMockDAO() throws Exception {
// mock
TargetService target = PowerMock.createPartialMock(TargetService.class, "method1", "method2");
// mock userDAO
UserDAO userDAO = PowerMock.createMock( UserDAO.class );
// 返回数据的准备
User user = new User();
int userId = 28;
user.setNickname( "ニックネーム" );
user.setUserid( userId );
// 既然是mock的dao,那么想得到什么都由自己定,脱离了真实的DB环境
EasyMock.expect( userDAO.getUser( EasyMock.anyInt() ) ).andReturn( user );
PowerMock.replay(userDAO);
// 将mock userDao注入到目标类中
target.setUserDAO( userDAO );

PowerMock.replay(target);
// Dao已经被mock了,接下来根据自己的需求做一些事情
...

// 验证正确性
Assert.assertEquals(expected, actual);

PowerMock.verify(userDAO);
PowerMock.verify(target);
}

/**
* mock Http,使得测试脱离外部环境,不需要真的去进行Http请求
* @throws Exception
*/
@Test
public void testMockHttp() throws Exception {
// mock HttpClient
DefaultHttpClient httpClient = PowerMock.createMock(DefaultHttpClient.class);
PowerMock.expectNew(DefaultHttpClient.class).andStubReturn(httpClient);

// mock HttpResponse
HttpResponse response = PowerMock.createMock(HttpResponse.class);
EasyMock.expect(httpClient.execute(EasyMock.anyObject(HttpUriRequest.class))).andStubReturn(response);

StatusLine statusLine = PowerMock.createMock(StatusLine.class);
EasyMock.expect(response.getStatusLine()).andStubReturn(statusLine);

// 设定期望的http status code,也可以是404,500等
EasyMock.expect(statusLine.getStatusCode()).andStubReturn(200);

HttpEntity entity = PowerMock.createMock(HttpEntity.class);
EasyMock.expect(response.getEntity()).andStubReturn(entity);
// 设定期望的http响应结果,这里用一个字符串来作为返回值
InputStream inputStream = new ByteArrayInputStream("code:E01".getBytes());
EasyMock.expect(entity.getContent()).andReturn(inputStream);

// 已经得到了期望的Http请求结果,接下来根据自己的需求做一些事情
...

PowerMock.replayAll();
// 验证正确性
Assert.assertEquals(expected, actual);
PowerMock.verifyAll();
}
}

测试log4j需要的自定义的mock log类:

package com.project.mock;

import java.util.ArrayList;
import java.util.List;

import org.apache.commons.logging.Log;

/**
* 这是一个自定义的log类,用于mock真实的log4j对象,它可以模拟log4j的各种动作,并且可以订制各种我们希望的动作
* 这里只模仿两个动作,一个是单纯的接收一条message,一个是接收message同时接收一个exception
* 这样一来,真实代码中要用到log4j对象记录log的地方,都被这个mock log给替换了,并且所有记录的信息都被记录到这个对象中,供测试用
* @throws Exception
*/
public class MockLog implements Log {
private List<Object> logList = new ArrayList<Object>();
private List<Throwable> exceptionList = new ArrayList<Throwable>();

@Override
public void debug(Object arg0) {
logList.add(arg0);
}

@Override
public void debug(Object arg0, Throwable arg1) {
logList.add(arg0);
exceptionList.add( arg1 );
}

@Override
public void error(Object arg0) {
logList.add(arg0);
}

@Override
public void error(Object arg0, Throwable arg1) {
logList.add(arg0);
exceptionList.add( arg1 );
}

@Override
public void fatal(Object arg0) {
}

@Override
public void fatal(Object arg0, Throwable arg1) {
logList.add(arg0);
exceptionList.add( arg1 );
}

@Override
public void info(Object arg0) {
logList.add(arg0);
}

@Override
public void info(Object arg0, Throwable arg1) {
logList.add(arg0);
exceptionList.add( arg1 );
}

@Override
public boolean isDebugEnabled() {
return false;
}

@Override
public boolean isErrorEnabled() {
return false;
}

@Override
public boolean isFatalEnabled() {
return false;
}

@Override
public boolean isInfoEnabled() {
return false;
}

@Override
public boolean isTraceEnabled() {
return false;
}

@Override
public boolean isWarnEnabled() {
return false;
}

@Override
public void trace(Object arg0) {
logList.add(arg0);
}

@Override
public void trace(Object arg0, Throwable arg1) {
logList.add(arg0);
exceptionList.add( arg1 );
}

@Override
public void warn(Object arg0) {
logList.add(arg0);
}

@Override
public void warn(Object arg0, Throwable arg1) {
logList.add(arg0);
exceptionList.add( arg1 );
}

public List<Object> getLogList() {
return logList;
}

public void setLogList(List<Object> logList) {
this.logList = logList;
}

public void setExceptionList( List<Throwable> exceptionList ) {
this.exceptionList = exceptionList;
}

public List<Throwable> getExceptionList() {
return exceptionList;
}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值