使用mock进行单元测试

时间:2022-08-14 23:18:37

在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的方法,会返回预先设置的返回值或抛出异常。最后再对测试代码进行验证。


  1. mport static org.mockito.Mockito.*;  
  2.    
  3. //创建Mock  
  4. List mockedList = mock(List.class);  
  5.    
  6. //使用Mock对象  
  7. mockedList.add("one");  
  8. mockedList.clear();  
  9.    
  10. //验证行为  
  11. verify(mockedList).add("one");  
  12. 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;

}