`
lovelease
  • 浏览: 385958 次
社区版块
存档分类
最新评论

用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;
	}
}

分享到:
评论

相关推荐

    使用PowerMock来Mock静态函数

    标题“使用PowerMock来Mock静态函数”指的是如何利用PowerMock库来对Java中的静态方法进行模拟测试。静态方法由于其非实例化特性,通常难以通过常规的单元测试方式进行隔离和测试,因为它们不依赖于对象的状态。...

    利用PowerMock模拟静态方法和私有方法的示例

    PowerMock允许我们使用`@PrepareForTest`注解指定需要模拟的类,并通过`PowerMockito.mockStatic`或`Mockito.when`来模拟私有方法。 下面是一段使用PowerMock模拟静态方法和私有方法的示例代码: ```java import ...

    Instant Mock Testing with PowerMock.pdf

    Instant Mock Testing with PowerMock 7 Saying Hello World! (Simple) 8 Getting and installing PowerMock (Simple) 14 Mocking static methods (Simple) 22 Verifying method invocation (Simple) 28 Mocking ...

    powermock单元测试

    3. **模拟静态方法**:使用`PowerMockito.mockStatic(Class&lt;?&gt; clazz)`来模拟静态方法。然后通过`when`和`thenReturn`(或其他方法)来定义静态方法的行为。 4. **模拟私有方法**:首先,需要使用`PowerMockito.spy...

    powermock-module-junit4-2.0.9-API文档-中英对照版.zip

    赠送jar包:powermock-module-junit4-2.0.9.jar; 赠送原API文档:powermock-module-junit4-2.0.9-javadoc.jar; 赠送源代码:powermock-module-junit4-2.0.9-sources.jar; 赠送Maven依赖信息文件:powermock-...

    powermock依赖jar文件.rar

    在Java开发中,有时我们需要对不可Mock的对象进行单元测试,PowerMock提供了解决这类问题的能力。 标题中的"powermock依赖jar文件.rar"指的是包含PowerMock运行所需的JAR库文件的压缩包。这个压缩包可能是用户在...

    powermock

    PowerMock 提供了 `PowerMockito.mockStatic` 方法,允许我们指定静态方法的行为,从而在测试中隔离静态方法的依赖。 3. **构造函数模拟**: 有些情况下,被测试类可能依赖于私有构造函数或不可实例化的类。...

    PowerMock实战手册

    4. **模拟构造函数**:对于不允许mock的构造函数,PowerMock可以帮助我们在测试中创建特定的实例。 5. **控制静态初始化器**:静态初始化器可能在不期望的时候被执行,PowerMock可以禁用它们,避免干扰测试。 通过...

    汪文君powermock实战教学

    【PowerMock实战教学】是由汪文君主讲的一系列教程,专注于讲解如何使用PowerMock这一强大的Java单元测试框架。PowerMock是在easymock和mockito的基础上构建的,旨在提供更多的功能,解决传统mock框架无法处理的一些...

    powermock-module-junit4-common-2.0.9-API文档-中英对照版.zip

    赠送jar包:powermock-module-junit4-common-2.0.9.jar; 赠送原API文档:powermock-module-junit4-common-2.0.9-javadoc.jar; 赠送源代码:powermock-module-junit4-common-2.0.9-sources.jar; 赠送Maven依赖信息...

    PowerMock实战

    在后续章节中,将会进一步深入讲解PowerMock的高级特性,比如如何模拟局部变量(MockLocalVariable),如何模拟静态方法(MockStatic)以及如何使用验证(Verifying)。此外,本书还介绍了如何模拟私有方法、构造...

    EasyMock and PowerMock入门PPT

    4. 在测试方法中使用Mock对象。 5. 使用`verify()`确保所有录制的方法都被调用。 **其他用法** - 指定期望的调用次数。 - 指定返回值。 - 处理异常。 - 创建自定义的返回值和异常。 **PowerMock的引入** ...

    powermock-mockito-junit-1.6.2.zip

    4. 使用Mockito的API创建mock对象并设置期望行为。 5. 使用PowerMock的API模拟静态方法、final类或方法等。 6. 编写测试方法,调用要测试的代码,并使用Mockito验证方法调用是否符合预期。 通过以上步骤,开发者...

    mock 介绍及原理,前后端 mock方法

    在后端开发中,Mock 可以使用框架如 Mockito、PowerMock、Mockserver、Moco 等,对服务的请求和响应进行模拟。 Mock 的好处包括: * 可以并行工作,不需要等待依赖方的开发完成 * 可以方便构造出各种异常的场景,...

    powerMock的测试样例集合

    4. **Answer Interface**: PowerMock的`Answer`接口用于自定义模拟方法的响应。当你需要根据调用参数动态返回结果时,可以实现`Answer`接口,并在`answer`方法中编写业务逻辑。 5. **Argument Matcher**: `...

    PowerMock+Mockito-junit测试套件1.6.3版本

    例如,使用PowerMock模拟难以测试的部分,用Mockito定义mock对象的行为,最后由JUnit执行并报告测试结果。通过这种方式,开发者可以确保代码的质量和可靠性,提高软件的稳定性。同时,这个版本的测试套件也意味着它...

    PowerMock.zip

    这个压缩包“PowerMock.zip”可能包含PowerMock库的jar文件和其他相关资源,帮助开发者在他们的项目中集成和使用PowerMock。 PowerMock 的核心功能在于它的模拟能力。在单元测试中,我们通常希望隔离被测试代码,只...

Global site tag (gtag.js) - Google Analytics