Mockito单元测试


目录

  1. Mock测试的概念
  2. Mockito的使用
  3. Mock静态方法

参考:

Mock测试的概念

单元测试,是验证代码逻辑一个非常重要的手段。其中Mockito单元测试包,可以对Bean依赖的外部Bean逻辑进行Mock,使得开发人员只需要关注本Bean内的逻辑正确与否

Mockito的使用

  • 依赖

    <dependency>
      	<groupId>junit</groupId>
      	<artifactId>junit</artifactId>
      	<version>4.9</version>
    </dependency>
    <dependency>
      	<groupId>org.mockito</groupId>
      	<artifactId>mockito-all</artifactId>
      	<version>1.10.19</version>
    </dependency>
  • 模板

    @RunWith(MockitoJunitRunner.class)
    public class Test{
      
      // 待测试的类
      private TestService testService;
      
      // 一些其他属性
      
      // 在testService需要测试的方法中,有外部依赖的Bean,进行Mock操作
      @Mock
      private UsedBean1 u1;
      @Mock
      private UsedBean2 u2;
      
      @Before
      public void before(){
        // 创建测试对象
        testService = new TestService();
        testService.setU1(u1);
        testService.setU2(u2);
        
        // 其他逻辑
      }
      
      // 测试方法
      @Test
      public void test(){
        // Mock外部依赖Bean的方法
        Mockito.when(u1.method1(Mockito.any())).thenReturn("...");
        Mockito.when(u2.method2(Mockito.any())).thenReturn("...");
        
        // 其他测试参数设置
        
        // 测试方法
        String result = testService.test();
        Assert.equals(result, new Result().toString());
      }
      
      	// 测试抛异常逻辑
        @Test
        public void exception_test(){
            try {
    			long data = Long.parseLong("???");
    			// fail("NumberFormatException is not thrown as expected");
    		} catch (Exception e) {
    			assertTrue(e != null);
    		}
        }
    
        // 测试priavte方法
        @Test
        public void private_method_test(){
            // 使用java的反射机制
            Class<TestService> clz = testService.getClass();
            // 测试TestService的 private String test(Long arg)方法
            Method method = clz.getDeclaredMethod("test", Long.class);
            method.setAccessible(true);
            Assert.assertEquals("1", method.invoke(testService, 1));
            method.setAccessible(false);
        }
      
    }

Mock静态方法

需要使用powerMock

  • 依赖
<!--PowerMock-->
      <dependency>
          <groupId>org.powermock</groupId>
          <artifactId>powermock-api-mockito</artifactId>
          <version>1.6.2</version>
          <scope>test</scope>
      </dependency>

      <dependency>
          <groupId>org.powermock</groupId>
          <artifactId>powermock-module-junit4</artifactId>
          <version>1.6.2</version>
          <scope>test</scope>
      </dependency>

注意和mockito的依赖版本兼容性

Mockito                     PowerMock
1.10.8+                     1.6.2+
1.9.5-rc1 - 1.9.5           1.5.0 - 1.5.6
1.9.0-rc1 & 1.9.0           1.4.10 - 1.4.12
1.8.5                       1.3.9 to 1.4.9
1.8.4                       1.3.7 & 1.3.8 
1.8.3                       1.3.6
1.8.1 & 1.8.2               1.3.5
1.8                         1.3
1.7                         1.2.5
  • 测试类
public class ClassUnderTest {
    public boolean callStaticMethod() {
        return ClassDependency.isExist(); 
    }  
}

public class ClassDependency {
    public static boolean isExist() {
        return false; 
    } 
}

@RunWith(PowerMockRunner.class) 
@PrepareForTest(value = {ClassDependency.class})
public class TestClassUnderTest {

    @Test 
    public void testCallStaticMethod() {
        ClassUnderTest underTest = new ClassUnderTest();
        PowerMockito.mockStatic(ClassDependency.class); 
        PowerMockito.when(ClassDependency.isExist()).thenReturn(true);
        Assert.assertTrue(underTest.callStaticMethod());
    }
}
  • 避坑

直接启动有时候会报错

ERROR Could not reconfigure JMX java.lang.LinkageError: loader constraint violation: loader (instance of org/powermock/core/classloader/MockClassLoader) previously initiated loading for a different type with name "javax/management/MBeanServer"
	at java.lang.ClassLoader.defineClass1(Native Method)
	at java.lang.ClassLoader.defineClass(Unknown Source)
	at org.powermock.core.classloader.MockClassLoader.loadUnmockedClass(MockClassLoader.java:262)
	at org.powermock.core.classloader.MockClassLoader.loadModifiedClass(MockClassLoader.java:206)
	at org.powermock.core.classloader.DeferSupportingClassLoader.loadClass1(DeferSupportingClassLoader.java:89)
	at org.powermock.core.classloader.DeferSupportingClassLoader.loadClass(DeferSupportingClassLoader.java:79)
	at java.lang.ClassLoader.loadClass(Unknown Source)
	at org.apache.logging.log4j.core.jmx.Server.unregisterAllMatching(Server.java:335)
	at org.apache.logging.log4j.core.jmx.Server.unregisterLoggerContext(Server.java:259)
	at org.apache.logging.log4j.core.jmx.Server.reregisterMBeansAfterReconfigure(Server.java:164)
	at org.apache.logging.log4j.core.jmx.Server.reregisterMBeansAfterReconfigure(Server.java:140)
	at org.apache.logging.log4j.core.LoggerContext.setConfiguration(LoggerContext.java:556)
	at org.apache.logging.log4j.core.LoggerContext.reconfigure(LoggerContext.java:617)
	at org.apache.logging.log4j.core.LoggerContext.reconfigure(LoggerContext.java:634)
	at org.apache.logging.log4j.core.LoggerContext.start(LoggerContext.java:229)
	at org.apache.logging.log4j.core.impl.Log4jContextFactory.getContext(Log4jContextFactory.java:152)
	at org.apache.logging.log4j.core.impl.Log4jContextFactory.getContext(Log4jContextFactory.java:45)
	at org.apache.logging.log4j.LogManager.getContext(LogManager.java:194)
	at org.apache.logging.log4j.spi.AbstractLoggerAdapter.getContext(AbstractLoggerAdapter.java:122)
	at org.apache.logging.slf4j.Log4jLoggerFactory.getContext(Log4jLoggerFactory.java:43)
	at org.apache.logging.log4j.spi.AbstractLoggerAdapter.getLogger(AbstractLoggerAdapter.java:46)
	at org.apache.logging.slf4j.Log4jLoggerFactory.getLogger(Log4jLoggerFactory.java:29)
	at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:358)
	at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:383)

需要在测试类上添加这个注解即可

@PowerMockIgnore({"javax.management.*"})

文章作者: 小小千千
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 小小千千 !
评论
  目录