mirror of
https://github.com/alibaba/testable-mock.git
synced 2025-02-15 22:30:24 +08:00
fix bytecode order and async test case
This commit is contained in:
parent
2fda70d7b4
commit
26712108d6
@ -83,10 +83,11 @@ public class TestClassHandler extends BaseClassHandler {
|
|||||||
private AbstractInsnNode[] replaceTestableUtilField(MethodNode mn, AbstractInsnNode[] instructions,
|
private AbstractInsnNode[] replaceTestableUtilField(MethodNode mn, AbstractInsnNode[] instructions,
|
||||||
String fieldName, int pos) {
|
String fieldName, int pos) {
|
||||||
InsnList insnNodes = new InsnList();
|
InsnList insnNodes = new InsnList();
|
||||||
insnNodes.insert(new VarInsnNode(ALOAD, 0));
|
// NOTE: will insert in reversed order
|
||||||
insnNodes.insert(new MethodInsnNode(INVOKESTATIC, CLASS_TESTABLE_UTIL, FIELD_TO_METHOD_MAPPING.get(fieldName),
|
insnNodes.insert(new MethodInsnNode(INVOKESTATIC, CLASS_TESTABLE_UTIL, FIELD_TO_METHOD_MAPPING.get(fieldName),
|
||||||
SIGNATURE_TESTABLE_UTIL_METHOD, false));
|
SIGNATURE_TESTABLE_UTIL_METHOD, false));
|
||||||
mn.instructions.insertBefore(instructions[pos], insnNodes);
|
insnNodes.insert(new VarInsnNode(ALOAD, 0));
|
||||||
|
mn.instructions.insert(instructions[pos], insnNodes);
|
||||||
mn.instructions.remove(instructions[pos]);
|
mn.instructions.remove(instructions[pos]);
|
||||||
return mn.instructions.toArray();
|
return mn.instructions.toArray();
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,14 @@ package com.alibaba.testable.core.tool;
|
|||||||
*/
|
*/
|
||||||
public class TestableTool {
|
public class TestableTool {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Name of current test case method
|
||||||
|
*/
|
||||||
public static String TEST_CASE;
|
public static String TEST_CASE;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Name of the last visited method in source class
|
||||||
|
*/
|
||||||
public static String SOURCE_METHOD;
|
public static String SOURCE_METHOD;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,10 @@ import java.io.*;
|
|||||||
*/
|
*/
|
||||||
public class ResourceUtil {
|
public class ResourceUtil {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read content of a text file from resource folder
|
||||||
|
* @param filePath file to read
|
||||||
|
*/
|
||||||
public static String fetchText(String filePath) {
|
public static String fetchText(String filePath) {
|
||||||
InputStream in = ResourceUtil.class.getResourceAsStream("/" + filePath);
|
InputStream in = ResourceUtil.class.getResourceAsStream("/" + filePath);
|
||||||
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
|
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
|
||||||
@ -24,6 +28,10 @@ public class ResourceUtil {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read content of a binary file from resource folder
|
||||||
|
* @param filePath file to read
|
||||||
|
*/
|
||||||
public static byte[] fetchBinary(String filePath) {
|
public static byte[] fetchBinary(String filePath) {
|
||||||
InputStream in = ResourceUtil.class.getResourceAsStream("/" + filePath);
|
InputStream in = ResourceUtil.class.getResourceAsStream("/" + filePath);
|
||||||
if (in == null) {
|
if (in == null) {
|
||||||
|
@ -7,6 +7,11 @@ import java.util.List;
|
|||||||
*/
|
*/
|
||||||
public class StringUtil {
|
public class StringUtil {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Join strings
|
||||||
|
* @param list strings to join
|
||||||
|
* @param conjunction connection character
|
||||||
|
*/
|
||||||
static public String join(List<String> list, String conjunction)
|
static public String join(List<String> list, String conjunction)
|
||||||
{
|
{
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
|
@ -7,19 +7,27 @@ import com.alibaba.testable.core.constant.ConstPool;
|
|||||||
*/
|
*/
|
||||||
public class TestableUtil {
|
public class TestableUtil {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the last visit method in source file
|
||||||
|
* @param testClassRef usually `this` variable of the test class
|
||||||
|
* @return method name
|
||||||
|
*/
|
||||||
public static String currentSourceMethodName(Object testClassRef) {
|
public static String currentSourceMethodName(Object testClassRef) {
|
||||||
Class<?> testClass = testClassRef.getClass();
|
Class<?> testClass = testClassRef.getClass();
|
||||||
StackTraceElement[] stack = getMainThread().getStackTrace();
|
|
||||||
String testClassName = getRealClassName(testClass);
|
String testClassName = getRealClassName(testClass);
|
||||||
String sourceClassName = testClassName.substring(0, testClassName.length() - ConstPool.TEST_POSTFIX.length());
|
String sourceClassName = testClassName.substring(0, testClassName.length() - ConstPool.TEST_POSTFIX.length());
|
||||||
for (int i = stack.length - 1; i >= 0; i--) {
|
String sourceMethod = findLastMethodFromSourceClass(sourceClassName, getMainThread().getStackTrace());
|
||||||
if (stack[i].getClassName().equals(sourceClassName)) {
|
if (sourceMethod.isEmpty()) {
|
||||||
return stack[i].getMethodName();
|
return findLastMethodFromSourceClass(sourceClassName, Thread.currentThread().getStackTrace());
|
||||||
}
|
}
|
||||||
}
|
return sourceMethod;
|
||||||
return "";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get current test case method
|
||||||
|
* @param testClassRef usually `this` variable of the test class
|
||||||
|
* @return method name
|
||||||
|
*/
|
||||||
public static String currentTestCaseName(Object testClassRef) {
|
public static String currentTestCaseName(Object testClassRef) {
|
||||||
Class<?> testClass = testClassRef.getClass();
|
Class<?> testClass = testClassRef.getClass();
|
||||||
StackTraceElement[] stack = getMainThread().getStackTrace();
|
StackTraceElement[] stack = getMainThread().getStackTrace();
|
||||||
@ -32,6 +40,15 @@ public class TestableUtil {
|
|||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static String findLastMethodFromSourceClass(String sourceClassName, StackTraceElement[] stack) {
|
||||||
|
for (StackTraceElement element : stack) {
|
||||||
|
if (element.getClassName().equals(sourceClassName)) {
|
||||||
|
return element.getMethodName();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
private static String getRealClassName(Class<?> testClass) {
|
private static String getRealClassName(Class<?> testClass) {
|
||||||
String className = testClass.getName();
|
String className = testClass.getName();
|
||||||
int posOfInnerClass = className.lastIndexOf('$');
|
int posOfInnerClass = className.lastIndexOf('$');
|
||||||
@ -44,6 +61,7 @@ public class TestableUtil {
|
|||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// usually impossible to go here
|
||||||
return Thread.currentThread();
|
return Thread.currentThread();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@ import com.alibaba.testable.core.annotation.TestableInject;
|
|||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import java.util.concurrent.Callable;
|
import java.util.concurrent.Callable;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
|
||||||
import static com.alibaba.testable.core.tool.TestableTool.SOURCE_METHOD;
|
import static com.alibaba.testable.core.tool.TestableTool.SOURCE_METHOD;
|
||||||
import static com.alibaba.testable.core.tool.TestableTool.TEST_CASE;
|
import static com.alibaba.testable.core.tool.TestableTool.TEST_CASE;
|
||||||
@ -41,6 +42,9 @@ class DemoServiceTest {
|
|||||||
|
|
||||||
@TestableInject
|
@TestableInject
|
||||||
private String callFromDifferentMethod() {
|
private String callFromDifferentMethod() {
|
||||||
|
if (TEST_CASE.equals("should_able_to_get_test_case_name")) {
|
||||||
|
return "mock_special";
|
||||||
|
}
|
||||||
switch (SOURCE_METHOD) {
|
switch (SOURCE_METHOD) {
|
||||||
case "callerOne": return "mock_one";
|
case "callerOne": return "mock_one";
|
||||||
default: return "mock_others";
|
default: return "mock_others";
|
||||||
@ -81,15 +85,19 @@ class DemoServiceTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void should_able_to_get_source_method_name() throws Exception {
|
void should_able_to_get_source_method_name() throws Exception {
|
||||||
assertEquals("mock_one_mock_others", demoService.callerTwo() + "_" + demoService.callerOne());
|
// synchronous
|
||||||
assertEquals("mock_one_mock_others", ((Callable<String>)() ->
|
assertEquals("mock_one_mock_others", demoService.callerOne() + "_" + demoService.callerTwo());
|
||||||
demoService.callerOne() + "_" + demoService.callerTwo()).call());
|
// asynchronous
|
||||||
|
assertEquals("mock_one_mock_others",
|
||||||
|
Executors.newSingleThreadExecutor().submit(() -> demoService.callerOne() + "_" + demoService.callerTwo()).get());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void should_able_to_get_test_case_name() throws Exception {
|
void should_able_to_get_test_case_name() throws Exception {
|
||||||
assertEquals("should_able_to_get_test_case_name", TEST_CASE);
|
// synchronous
|
||||||
assertEquals("should_able_to_get_test_case_name", ((Callable<String>)() -> TEST_CASE).call());
|
assertEquals("mock_special", demoService.callerOne());
|
||||||
|
// asynchronous
|
||||||
|
assertEquals("mock_special", Executors.newSingleThreadExecutor().submit(() -> demoService.callerOne()).get());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@ import com.alibaba.testable.core.tool.TestableTool.SOURCE_METHOD
|
|||||||
import com.alibaba.testable.core.tool.TestableTool.TEST_CASE
|
import com.alibaba.testable.core.tool.TestableTool.TEST_CASE
|
||||||
import org.junit.jupiter.api.Assertions.assertEquals
|
import org.junit.jupiter.api.Assertions.assertEquals
|
||||||
import org.junit.jupiter.api.Test
|
import org.junit.jupiter.api.Test
|
||||||
import java.util.concurrent.Callable
|
import java.util.concurrent.Executors
|
||||||
|
|
||||||
|
|
||||||
@EnableTestable
|
@EnableTestable
|
||||||
@ -29,10 +29,16 @@ internal class DemoServiceTest {
|
|||||||
private fun startsWith(self: BlackBox, s: String) = false
|
private fun startsWith(self: BlackBox, s: String) = false
|
||||||
|
|
||||||
@TestableInject
|
@TestableInject
|
||||||
private fun callFromDifferentMethod() = when (SOURCE_METHOD) {
|
private fun callFromDifferentMethod(): String {
|
||||||
|
return if (TEST_CASE == "should_able_to_get_test_case_name") {
|
||||||
|
"mock_special"
|
||||||
|
} else {
|
||||||
|
when (SOURCE_METHOD) {
|
||||||
"callerOne" -> "mock_one"
|
"callerOne" -> "mock_one"
|
||||||
else -> "mock_others"
|
else -> "mock_others"
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private val demoService = DemoService()
|
private val demoService = DemoService()
|
||||||
|
|
||||||
@ -65,15 +71,21 @@ internal class DemoServiceTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun should_able_to_get_source_method_name() {
|
fun should_able_to_get_source_method_name() {
|
||||||
assertEquals("mock_one_mock_others", demoService.callerTwo() + "_" + demoService.callerOne())
|
// synchronous
|
||||||
assertEquals("mock_one_mock_others", Callable<String> {
|
assertEquals("mock_one_mock_others", demoService.callerOne() + "_" + demoService.callerTwo())
|
||||||
|
// asynchronous
|
||||||
|
assertEquals("mock_one_mock_others", Executors.newSingleThreadExecutor().submit<String> {
|
||||||
demoService.callerOne() + "_" + demoService.callerTwo()
|
demoService.callerOne() + "_" + demoService.callerTwo()
|
||||||
}.call())
|
}.get())
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun should_able_to_get_test_case_name() {
|
fun should_able_to_get_test_case_name() {
|
||||||
assertEquals("should_able_to_get_test_case_name", TEST_CASE)
|
// synchronous
|
||||||
assertEquals("should_able_to_get_test_case_name", Callable<String> { TEST_CASE }.call())
|
assertEquals("mock_special", demoService.callerOne())
|
||||||
|
// asynchronous
|
||||||
|
assertEquals("mock_special", Executors.newSingleThreadExecutor().submit<String> {
|
||||||
|
demoService.callerOne()
|
||||||
|
}.get())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user