alibaba / testable-mock

换种思路写Mock,让单元测试更简单
https://alibaba.github.io/testable-mock/
MIT License
1.83k stars 309 forks source link

0.5.1 报 java.lang.StringIndexOutOfBoundsException: String index out of range: -1 #109

Closed Article23399 closed 3 years ago

Article23399 commented 3 years ago

会报

[DIAGNOSE] Handling test class com/example/demo/TestServiceTest
[VERBOSE]    Test case "test"
[DIAGNOSE]   Found 1 test cases
[VERBOSE]    Mock method "test1" as "com.example.demo.TestService::test1(int) : int"
[VERBOSE]    Mock method "test2" as "com.example.demo.TestService::test2(int) : int"
[WARN] Failed to transform class com/example/demo/TestService
[DIAGNOSE] java.lang.StringIndexOutOfBoundsException: String index out of range: -1
[DIAGNOSE] Handling mock class com/example/demo/TestServiceTest$Mock
// com.example.demo.TestServiceTest.java
@RunWith(SpringRunner.class)
@SpringBootTest
public class TestServiceTest {
    @Autowired
    private TestService testService;

    @MockDiagnose(LogLevel.VERBOSE)
    public static class Mock {
        // 放置Mock方法的地方

        @MockMethod(targetClass = TestService.class, targetMethod = "test1")
        public int test1(int a) {
            System.out.println("test1方法被mock了");
            return a + 1;
        }

        @MockMethod(targetClass = TestService.class, targetMethod = "test2")
        private int test2(int a) {
            System.out.println("test2方法被mock了");
            System.out.println(SOURCE_METHOD);
            return a + 2;
        }

        // 注释不报,不注释报
        @MockMethod(targetClass = System.class, targetMethod = "loadLibrary")
        private void loadLibrary(String libname) {
            System.err.println("loadLibrary " + libname);
        }
    }

    @Test
    public void test() {
        System.out.println(testService.test1(1));
    }
}

// com.example.demo.TestService.java
@Service
public class TestService {

    public int test1(int a) {
        return test2(a);
    }

    private int test2(int a) {
        return 999;
    }
}

// com.example.demo.JNIClass.java
public class JNIClass {
    static {
        System.loadLibrary("native-lib");
    }

    public native String add(int a, int b);

    public String getAdd() {
        return add(2, 2);
    }
}
tiny-x commented 3 years ago

同样的问题

linfan commented 3 years ago

问题收到,今晚会做个复现然后看下为什么在发版前的回归测试没有发现出来

linfan commented 3 years ago

使用以上代码未复现问题。这里System.loadLibrary()的调用在JNIClass类型中,在TestServiceTest.Mock类里声明的loadLibrary()方法应该不会引发任何置换动作,试了将JNIClass中的方法移到TestService类中,此时Mock正常生效,没有遇到StringIndexOutOfBoundsException异常。

我们会排查一下可能导致下标溢出的逻辑,尝试下个版本里做个修复。如果有其他能复现此问题的代码,也欢迎提供。

Article23399 commented 3 years ago

使用以上代码未复现问题。

这是三个文件,我又新建了一个spirng boot项目试了下稳定复现

linfan commented 3 years ago

已定位,和@MockDiagnose(LogLevel.VERBOSE)功能有关,当Mock了返回值为void的方法,且开启VERBOSE级别调试日志的时候会复现。 已提交修复到主干,会包含在下个版本里。

linfan commented 3 years ago

0.5.2版本已发布,包含此问题的修复