## Android Studio 2.1.3配置Robolectric-3.0,Powermock-1.6.5单元测试环境

Android Studio提供了比较方便的单元测试，但是由于Android系统的限制(ClassloaderGoogle自己实现的，Powermock无法修改底层的bytecode)，目前Powermock还没办法直接在设备上执行测试，但是我们代码中难免存在一些静态对象，需要测试的时候，只能求助于PowermockRobolectric的组合。

1.首先在需要测试的项目的build.gradle中声明需要使用PowermockRobolectric

2.定义测试基类，在基类中声明一些必备的设置
AbsRobolectricPowerMockTest.java

3.定义真正的测试子类
DeckardActivityTest.java

## Beyond Mocking with PowerMock

PowerMock is a Java framework that allows you to for example mock static and final methods, final classes and construction of new objects. PowerMock is thus a powerful framework and it's quite easy to misuse it unless you know what you're doing. What I've seen time and again is that people are using mocking when what they probably should be doing is stubbing. With all the powerful features in PowerMock it can easily lead to complicated and hard-to-maintain test code.

## Mocking vs Stubbing

So what's the difference and why does it matter? Mocking can be summarized more in terms of a specification:

1. Setup how your mocks should behave in your test. This means creating a specification for the mocks involved in this particular test.
2. Perform the actual test
3. Verify that the interactions with the mocks matched the specification (created during setup)

Stubbing on the other hand doesn't require a specification to be fulfilled. What you do is to something like this:

1. Define what the collaborator methods should return when you run your test
2. Perform the actual test

Now if a collaborator happens to be called more than once, or perhaps not at all, doesn't really matter as long as the end result of the actual test behaves as expected.

So what does all this has to do with PowerMock? Well PowerMock has something called a “stubbing” API that let's you do quite many things without having to revert to mocking. You don't actually have to depend on any third-party mocking API either (like EasyMock and Mockito).

## Stubbing, suppressing and replacing with PowerMock

If all you need to do is stubbing a non-static public collaborator method you don't need PowerMock. You're probably better off with just vanilla Mockito or EasyMock. How ever if you want to stub a static or private method, suppressing a constructor or replacing a method PowerMock can help!

## Stubbing

So first consider stubbing a method with PowerMock. Consider the following simple Java class:

Let's say we want to stub the static hello method to always return an expected value using the PowerMock stubbing API:

Which means that a call to the hello method like this:

will now always return the string "Hello World".

Note that stub is statically imported from org.powermock.api.support.membermodification.MemberModifier and method from org.powermock.api.support.membermodification.MemberMatcher. You would also have to prepare MyClass1 for test using @PrepareForTest(MyClass1.class) and use the PowerMock runner
@RunWith(PowerMockRunner.class).
Stubbing a private method looks very similar:

## Suppressing

You can also suppress methods, constructors and fields that you're not interested in. Essentially what this means is that “this piece of code doesn't do anything useful for this particular test case, just get it out of the way”. For example consider the following class:

When unit testing the made-up hello method there's no need for us to load the “some.dll” so let's get rid of it:

It’s also possible to suppress all constructors of a class:

or all methods:

In this case all methods declared in SomeClass will return a default value.

You can also essentially suppress an entire class, meaning all methods, constructors and fields:

## Replacing

What if we only want to stub the hello method in MyClass1 when the parameter arg is equal to “John”? For all other arguments we like to invoke the original method. We can achieve this by replacing the method with an InvocationHandler like this:

This means that if you invoke MyClass1.hello("Someone") it'll return Hello Someone but calling it with John will return Hello John, you are awesome!.

You can also replace a method with another method! For example you may want to replace all log outputs in an integration test with your own method that simply prints everything to the console. Consider the following example:

Imagine that the Logger.debug(..) method logs to disk but in our test we simply want to print to the console. We could implement a new class for this:

And replace the Logger.debug(..) method with the ConsoleLogger.print(..) method in our test case:

This means that all calls to Logger.debug(..) will be replaced with ConsoleLogger.print(..). Note that this only works for static methods!

(Also note that in a real-life scenario there are most likely better ways to solve this problem, e.g. by simply configuring the original Logger to print to the console during our integration test).

## Conclusion

As you've hopefully seen there are more to PowerMock than just mocking. For example it's often better to simply stub third party api calls than to mock them. PowerMock has good support for doing this in a simple way even for legacy systems. As always PowerMock should be used with care so whenever you find the urge to use PowerMock make sure you look into possible alternatives as well.

# 目录

1. 需求知识

2. 使用 存根(Stub) 和 模拟对象(Mock Object) 进行测试

2.1. 为什么需要模拟？

2.2. 存根(Stub) vs. 模拟对象 (Mock)

2.3. 行为测试 vs. 状态测试

2.4. 生成模拟对象

3. 模拟框架( Mock Framework)

4. Mockito

4.1. 使用 Mockito 模拟对象

4.2. 使用 Mockito

4.3. Mockito的限制

4.4. 模拟对象的配置

4.5. 验证模拟对象的行为

4.6. Spy

5. Mockito 在 Android 平台测试

5.1. 在 Android 使用 Mockito

5.2. 安装

6. 链接和参考

## 2. 使用 存根(Stub) 和 模拟对象(Mock Object) 进行测试

### 2.3. 行为测试 vs. 状态测试

Mock 对象允许你对行为进行测试。有一些测试不需要验证结果，但是需要检查某些方法是否被正确的参数调用过。这种测试为行为测试。

## 3. 模拟框架( Mock Framework)

# jMock
http://jmock.org/
# EasyMock
http://easymock.org/
# Mockito
http://mockito.org/

## 4. Mockito

### 4.1. 使用 Mockito 模拟对象

Mockito 是比较流行的模拟框架，可以与JUnit 联合起来测试。它允许你进行创建和配置模拟对象。

Mockito的官方网站: Mockito 主页.

### 4.2. 使用 Mockito

Mockito 支持使用 mock() 静态方法创建模拟对象。

### 4.3. Mockito的限制

Mockito 以下的类型不能进行构造：

• 终态类(final classes)
• 匿名类(anonymous classes)
• 基本数据类型(primitive types)

### 4.4. 模拟对象的配置

Mockito 可以使用 verify() 方法来确认某些方法是否被调用过.

when(....).thenReturn(....) 结构可以为某些条件给定一个预期的返回值.

### 4.5. 验证模拟对象的行为

Mockito 跟踪了所有的方法调用和参数的调用情况。verify()可以验证方法的行为。

### 4.6. Spy

@Spy 或者方法 spy() 可以包含一个真实的对象. 每次调用，除非特出指定，委托给改真实对象的调用.

## 5. Mockito 在 Android 平台测试

### 5.1. 在 Android 使用 Mockito

Mockito 同样也可以在安卓平台上进行测试。

### 5.2. 安装

https://mockito.googlecode.com/files/mockito-all-1.9.5.jar
http://dexmaker.googlecode.com/files/dexmaker-1.0.jar
http://dexmaker.googlecode.com/files/dexmaker-mockito-1.0.jar