在service层,使用mock来测试代码。而不再使用Juint测试
JUint是java单元测试的框架,已经在Eclipse中默认的安装。目前主流的有JUnit3和JUnit4.JUint3中,测试用例需要继承TestCase类,JUint4中,测试用例无需继承TestCase类,只需要使用@Test等注解。
JUint4主要通过注解的方式来识别测试方法。目前支持的主要注解有:
@BeforeClass全局只会执行一次,而且是第一个运行。
@Before在测试方法运行之前运行
@Test测试方法
@After在测试方法运行之后允许
@AfterClass全局只会执行一次,而且是最后一个运行
@Ignore忽略此方法
Juint3和JUint4都提供了一个Assert类。Assert类中定义了很多静态方法来进行断言。
Mockito与JUint不同,并不是单元测试框架。它是用于生成模拟对象或者直接点说,就是“假对象”的工具。
Mock/Stub
Mock和Stub是两种测试代码功能的方法。Mock侧重于对功能的模拟,Stub测重于对功能的测试重现,例如对List接口。Mock会直接对List进行模拟,而Stub会新建一个实现了List的TestList,在其中编写测试的代码。
强烈建议优先选择Mock方式,因为Mock方式下,模拟代码与测试代码放在一起,易读性好,而且扩展性、灵活性都比Stub好。
比较流行的Mock
JMock
EasyMock
Mockito
powermock
其中EasyMcock和Mocking对于Java接口使用接口代理的方式来模拟。对于Java类使用继承的方式来模拟(即会创建一个新的Class类)。Mockito支持spy方式。可以对实例进行模拟。但他们都不能对静态方法和final类进行模拟。
Mockito是一个开源项目。Api相对于EasyMock更友好,与EasyMock不同的是,Mockito没有录制过程,只需要在“运行测试代码”之前对接口进行Stub,即设置方法的返回值或抛出的异常。然后直接运行测试代码。运行期间调用Mock的方法,会返回预先设置的返回值或抛出异常。最后再对测试代码进行验证。
- mport static org.mockito.Mockito.*;
- //创建Mock
- List mockedList = mock(List.class);
- //使用Mock对象
- mockedList.add("one");
- mockedList.clear();
- //验证行为
- verify(mockedList).add("one");
- verify(mockedList).clear();
首先是配置 Mock 对象,、
List mock = mock( List.class );
when( mock.get(0) ).thenReturn( 1 );
assertEquals( "预期返回1", 1, mock.get( 0 ) );
Mockito支持 迭代风格 的返回值设定,
- 第一种方式 when(i.next()).thenReturn("Hello").thenReturn("World");
- 第二种方式 when(i.next()).thenReturn("Hello", "World");
上面的例子等价于:
when(i.next()).thenReturn("Hello");
when(i.next()).thenReturn("World");
第一次调用i.next()将返回”Hello”,第二次的调用会返回”World”。
对 void 方法不返回值,所以不能 when(mock.someMethod()).thenReturn(value) 这样的语法,可以这样
doNothing().when(i).remove();
doThrow(Throwable) 模拟返回异常
doThrow(new RuntimeException()).when(i).remove();
迭代风格 doNothing().doThrow(new RuntimeException()).when(i).remove();,这样,第一次调用remove方法什么都不做,第二次调用抛出RuntimeException异常。
(1)如何将mock的类自动注入到待测类中?在测试代码中,使用@Inject将service层注入,@Mock注释Mapper。
public class AService {
}
public class AServiceTest extends Test4J{
@Inject(targets= { “ AService” })
@Mock
private AMapper aMapper;
}