在Android中正确测试静态方法

时间:2017-09-27 11:59:45

标签: java android unit-testing static mockito

我正在尝试使用

原则测试Android应用
  • 直接测试公共方法
  • 测试私有方法是测试公共方法的副作用
  • 独立测试静态方法

出于这个原因,我希望仅依靠JUnit和Mockito进行测试,而不是冒着滥用PowerMockito框架的风险

但是,在这种情况下测试公共方法时,我处于失速状态

public class ClassA {
    public void publicMethod(String id) {
        // something
        privateMethod(id);
    }

    public void privateMethod(String id) {
        // something
        StaticClass.staticMethod(id);
    }
}

因为在这里我可以为publicMethod写一个测试,但后来我面对了问题

  • 如何阻止StaticClass.staticMethod触发(模拟其行为/响应)?因为该方法可以在内部触摸任何内容,包括DB,HttpConnections,Context等等(特别是如果它来自我自己不写的类)

1 个答案:

答案 0 :(得分:2)

解决方案是:

  1. 将静态实用程序类包装在可模拟对象中。
  2. 不是在被测系统(SUT)中调用静态工具,而是在包装的类上传递依赖。
  3. 使用测试的@Before方法中的模拟包装类调用SUT的构造函数。
  4. 这符合OOP封装原则(BTW静态类可以破解)。例如:

    class WrappedStaticClass {
    
        void wrappedStaticMethod() {
            StaticClass.staticMethod();
        }
    }
    

    您重构的ClassA现在看起来像这样:

    public class ClassA {
    
        private final WrappedStaticClass wrappedStaticClass;
    
        public ClassA(WrappedStaticClass wrappedStaticClass) {
            this.wrappedStaticClass = wrappedStaticClass;
        }    
    
        public void publicMethod(String id) {
            // something
            privateMethod(id);
        }
    
        private void privateMethod(String id) {
            // something
            wrappedStaticClass.wrappedStaticMethod(id);
        }
    }
    

    您的测试现在看起来像这样:

    @Mock WrappedStaticClass mockWrappedStaticClass;
    
    //system under test
    ClassA classA;
    
    @Before
    public void setUp() {
        MockitoAnnotations.init(this);
        classA = new ClassA(mockWrappedStaticClass);
    }
    
    @Test
    public void testCallsWrappedStaticClass() {
        //act
        classA.publicMethod(1);
    
        //assert
        verify(mockWrappedStaticClass).wrappedStaticMethod();
    }