testable-mock
testable-mock copied to clipboard
直接调用的方法被Mock后不生效,间接调用的生效
版本: <testable.version>0.7.7</testable.version>
被测试类 public class MockDemo { public String callCommonFunc() { return commonFunc(); } public String commonFunc(){ return MockDemo.class.getSimpleName(); } }
测试类 @EnablePrivateAccess class MockDemoTest { @MockDiagnose(LogLevel.VERBOSE) public static class Mock { // @MockInvoke(targetClass = MockDemo.class, targetMethod = "commonFunc") // public String commonFunc() { // return "mock"; // } @MockInvoke public String commonFunc(MockDemo self) { System.out.println(self); return "mock"; } @MockInvoke(targetClass = MockDemo.class) public String callCommonFunc() { return "mock"; } } @Test public void mock(){ MockDemo u = new MockDemo(); assertEquals("mock", u.callCommonFunc()); assertEquals("mock", u.commonFunc()); } }
错误日志
[DIAGNOSE] Found source class io/MockDemo
[VERBOSE] Found method
org.opentest4j.AssertionFailedError: Expected :mock Actual :MockDemo
Mock只对业务类中的调用生效,因为Mock的目的本来就是在测试的时候,需要在不直接修改业务类代码的前提下,绕过业务类代码中的外部调用(或其他会影响测试的调用)。
对于测试方法里直接发起的调用,不应当被Mock。
是这个场景 **业务类有两个方法,**如:MockDemo callCommonFunc commonFunc public String callCommonFunc() { return commonFunc(); } public String commonFunc(){ return MockDemo.class.getSimpleName(); }
现在想mock上面两个方法: 类似如下的配置 @MockInvoke(targetClass = MockDemo.class, targetMethod = "commonFunc") @MockInvoke(targetClass = MockDemo.class) public String callCommonFunc()
commonFunc生效了,而callCommonFunc不生效
首先Testable Mock的方法的调用,而不是方法本身。举例来说,假设原本代码是:
public String callCommonFunc() {
return commonFunc(); <--- 这个是调用,在测试运行的时候会被自动替换
}
public String commonFunc() { <--- 这个方法本身是不会被改动的
return MockDemo.class.getSimpleName();
}
然后在同一个Mock方法上,只支持一个@MockInvoke
注解,如果有两个@MockInvoke的话,只有第一个会生效(这里的第一个是指生成字节码后的第一个,和源码里的注解顺序可能不一致)。因此因为targetMethod
参数的作用,上述代码实际上就只Mock了commonFunc
方法。
刚才贴的少了2行,看初始内容,是mock了两个方法,写的方式如下 @MockInvoke public String commonFunc(MockDemo self) { System.out.println(self); return "mock"; } @MockInvoke public String commonFunc(MockDemo self) { System.out.println(self); return "mock"; }
然后测试时,commonFunc不生效 public void mock(){ MockDemo u = new MockDemo(); assertEquals("mock", u.callCommonFunc()); assertEquals("mock", u.commonFunc()); }
理解了系统的设计方式,https://alibaba.github.io/testable-mock/#/zh-cn/doc/design-and-mechanism 划重点:Mock的目标是被测类中的方法调用。测试用例里的代码不会被Mock,方法的定义本身没有变化,只是发起调用的代码被替换了
这种场景如何来做:
class Demo{
public String test(){
...
this.innerFunc();
...
return ....;
}
}
假设我想mock: new Demo().test() 这个方法,那需要对代码逻辑进行修改才能mock,不然只是方法内的调用可以被mock,那就只能mock这个函数innerFunc
这种情况对一些已有的系统的测试就有些麻烦,不知有没有方式来支持这个场景 没深入testable-mock的代码,如果这种场景不支持,具体是什么原因
是啊,这种直接的对被测试的方法进行mock,难道还要打桩吗