mirror of
https://github.com/alibaba/testable-mock.git
synced 2025-01-09 20:00:21 +08:00
refactor test code, and omni constructor test
This commit is contained in:
parent
206fc5486e
commit
606760d632
@ -1,11 +1,8 @@
|
||||
package com.alibaba.demo.basic;
|
||||
|
||||
import com.alibaba.demo.basic.model.BlackBox;
|
||||
import com.alibaba.demo.basic.model.Box;
|
||||
import com.alibaba.demo.basic.model.Color;
|
||||
import com.alibaba.demo.basic.model.BlackBox;
|
||||
import com.alibaba.demo.basic.model.Box;
|
||||
import com.alibaba.demo.basic.model.Color;
|
||||
import com.alibaba.demo.basic.model.mock.BlackBox;
|
||||
import com.alibaba.demo.basic.model.mock.Box;
|
||||
import com.alibaba.demo.basic.model.mock.Color;
|
||||
|
||||
/**
|
||||
* 演示父类变量引用子类对象时的Mock场景
|
||||
|
@ -1,8 +1,7 @@
|
||||
package com.alibaba.demo.basic;
|
||||
|
||||
|
||||
import com.alibaba.demo.basic.model.BlackBox;
|
||||
import com.alibaba.demo.basic.model.BlackBox;
|
||||
import com.alibaba.demo.basic.model.mock.BlackBox;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
|
@ -1,7 +1,6 @@
|
||||
package com.alibaba.demo.basic;
|
||||
|
||||
import com.alibaba.demo.basic.model.BlackBox;
|
||||
import com.alibaba.demo.basic.model.BlackBox;
|
||||
import com.alibaba.demo.basic.model.mock.BlackBox;
|
||||
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
|
@ -1,4 +1,4 @@
|
||||
package com.alibaba.demo.basic.model;
|
||||
package com.alibaba.demo.basic.model.mock;
|
||||
|
||||
public class BlackBox extends Box implements Color {
|
||||
|
@ -1,4 +1,4 @@
|
||||
package com.alibaba.demo.basic.model;
|
||||
package com.alibaba.demo.basic.model.mock;
|
||||
|
||||
abstract public class Box {
|
||||
|
@ -1,4 +1,4 @@
|
||||
package com.alibaba.demo.basic.model;
|
||||
package com.alibaba.demo.basic.model.mock;
|
||||
|
||||
public interface Color {
|
||||
|
@ -0,0 +1,43 @@
|
||||
package com.alibaba.demo.basic.model.omni;
|
||||
|
||||
public class Child {
|
||||
|
||||
/**
|
||||
* An inner class
|
||||
*/
|
||||
public class SubChild {
|
||||
private GrandChild gc;
|
||||
|
||||
public GrandChild getGrandChild() {
|
||||
return gc;
|
||||
}
|
||||
|
||||
public void setGrandChild(GrandChild grandChild) {
|
||||
this.gc = grandChild;
|
||||
}
|
||||
}
|
||||
|
||||
// ---------- Member fields ----------
|
||||
|
||||
private GrandChild gc;
|
||||
|
||||
private EnumChild ec;
|
||||
|
||||
// ---------- Getters and Setters ----------
|
||||
|
||||
public GrandChild getGrandChild() {
|
||||
return gc;
|
||||
}
|
||||
|
||||
public void setGrandChild(GrandChild grandChild) {
|
||||
this.gc = grandChild;
|
||||
}
|
||||
|
||||
public EnumChild getEnumChild() {
|
||||
return ec;
|
||||
}
|
||||
|
||||
public void setEnumChild(EnumChild enumChild) {
|
||||
this.ec = enumChild;
|
||||
}
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
package com.alibaba.demo.basic.model.omni;
|
||||
|
||||
public enum EnumChild {
|
||||
|
||||
/**
|
||||
* demo value - 1
|
||||
*/
|
||||
VAL1,
|
||||
|
||||
/**
|
||||
* demo value - 2
|
||||
*/
|
||||
VAL2
|
||||
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
package com.alibaba.demo.basic.model.omni;
|
||||
|
||||
public class GrandChild {
|
||||
|
||||
// ---------- Member fields ----------
|
||||
|
||||
private int value;
|
||||
|
||||
// ---------- Constructor, Getters and Setters ----------
|
||||
|
||||
public GrandChild(int v) {
|
||||
this.value = v;
|
||||
}
|
||||
|
||||
public int getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setValue(int value) {
|
||||
this.value = value;
|
||||
}
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
package com.alibaba.demo.basic.model.omni;
|
||||
|
||||
public class Parent {
|
||||
|
||||
// ---------- Member fields ----------
|
||||
|
||||
private Child c;
|
||||
|
||||
private Child[] cs;
|
||||
|
||||
private Child.SubChild sc;
|
||||
|
||||
// ---------- Getters and Setters ----------
|
||||
|
||||
public Child getChild() {
|
||||
return c;
|
||||
}
|
||||
|
||||
public void setChild(Child child) {
|
||||
this.c = child;
|
||||
}
|
||||
|
||||
public Child[] getChildren() {
|
||||
return cs;
|
||||
}
|
||||
|
||||
public void setChildren(Child[] children) {
|
||||
this.cs = children;
|
||||
}
|
||||
|
||||
public Child.SubChild getSubChild() {
|
||||
return sc;
|
||||
}
|
||||
|
||||
public void setSubChild(Child.SubChild subChild) {
|
||||
this.sc = subChild;
|
||||
}
|
||||
|
||||
}
|
@ -1,13 +1,9 @@
|
||||
package com.alibaba.demo.basic;
|
||||
|
||||
import com.alibaba.demo.basic.model.BlackBox;
|
||||
import com.alibaba.demo.basic.model.Box;
|
||||
import com.alibaba.demo.basic.model.Color;
|
||||
import com.alibaba.demo.basic.model.mock.BlackBox;
|
||||
import com.alibaba.demo.basic.model.mock.Box;
|
||||
import com.alibaba.demo.basic.model.mock.Color;
|
||||
import com.alibaba.testable.core.annotation.MockMethod;
|
||||
import com.alibaba.demo.basic.DemoInherit;
|
||||
import com.alibaba.demo.basic.model.BlackBox;
|
||||
import com.alibaba.demo.basic.model.Box;
|
||||
import com.alibaba.demo.basic.model.Color;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static com.alibaba.testable.core.matcher.InvokeVerifier.verify;
|
||||
@ -54,42 +50,42 @@ class DemoInheritTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
void should_able_to_mock_call_sub_object_method_by_parent_object() {
|
||||
void should_mock_call_sub_object_method_by_parent_object() {
|
||||
BlackBox box = (BlackBox)demoInherit.putIntoBox();
|
||||
verify("put_into_box").withTimes(1);
|
||||
assertEquals("put_data_into_box", box.get());
|
||||
}
|
||||
|
||||
@Test
|
||||
void should_able_to_mock_call_sub_object_method_by_sub_object() {
|
||||
void should_mock_call_sub_object_method_by_sub_object() {
|
||||
BlackBox box = demoInherit.putIntoBlackBox();
|
||||
verify("put_into_blackbox").withTimes(1);
|
||||
assertEquals("put_data_into_blackbox", box.get());
|
||||
}
|
||||
|
||||
@Test
|
||||
void should_able_to_mock_call_parent_object_method_by_parent_object() {
|
||||
void should_mock_call_parent_object_method_by_parent_object() {
|
||||
String content = demoInherit.getFromBox();
|
||||
verify("get_from_box").withTimes(1);
|
||||
assertEquals("get_from_box", content);
|
||||
}
|
||||
|
||||
@Test
|
||||
void should_able_to_mock_call_parent_object_method_by_sub_object() {
|
||||
void should_mock_call_parent_object_method_by_sub_object() {
|
||||
String content = demoInherit.getFromBlackBox();
|
||||
verify("get_from_blackbox").withTimes(1);
|
||||
assertEquals("get_from_blackbox", content);
|
||||
}
|
||||
|
||||
@Test
|
||||
void should_able_to_mock_call_interface_method_by_interface_object() {
|
||||
void should_mock_call_interface_method_by_interface_object() {
|
||||
String color = demoInherit.getColorViaColor();
|
||||
verify("get_color_from_color").withTimes(1);
|
||||
assertEquals("color_from_color", color);
|
||||
}
|
||||
|
||||
@Test
|
||||
void should_able_to_mock_call_interface_method_by_sub_class_object() {
|
||||
void should_mock_call_interface_method_by_sub_class_object() {
|
||||
String color = demoInherit.getColorViaBox();
|
||||
verify("get_color_from_blackbox").withTimes(1);
|
||||
assertEquals("color_from_blackbox", color);
|
||||
|
@ -19,7 +19,7 @@ class DemoInnerClassTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
void should_able_to_mock_invoke_inside_inner_class() throws Exception {
|
||||
void should_mock_invoke_inside_inner_class() throws Exception {
|
||||
DemoInnerClass demo = new DemoInnerClass();
|
||||
assertEquals("MockedCall", demo.callInnerDemo());
|
||||
assertEquals("MockedCall", demo.callAnonymousInner());
|
||||
|
@ -1,10 +1,8 @@
|
||||
package com.alibaba.demo.basic;
|
||||
|
||||
import com.alibaba.demo.basic.model.BlackBox;
|
||||
import com.alibaba.demo.basic.model.mock.BlackBox;
|
||||
import com.alibaba.testable.core.annotation.MockMethod;
|
||||
import com.alibaba.testable.core.error.VerifyFailedError;
|
||||
import com.alibaba.demo.basic.DemoMatcher;
|
||||
import com.alibaba.demo.basic.model.BlackBox;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static com.alibaba.testable.core.matcher.InvokeMatcher.*;
|
||||
|
@ -1,9 +1,8 @@
|
||||
package com.alibaba.demo.basic;
|
||||
|
||||
import com.alibaba.demo.basic.model.BlackBox;
|
||||
import com.alibaba.demo.basic.model.mock.BlackBox;
|
||||
import com.alibaba.testable.core.annotation.MockConstructor;
|
||||
import com.alibaba.testable.core.annotation.MockMethod;
|
||||
import com.alibaba.demo.basic.model.BlackBox;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
@ -73,20 +72,20 @@ class DemoMockTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
void should_able_to_mock_new_object() {
|
||||
void should_mock_new_object() {
|
||||
assertEquals("mock_something", demoMock.newFunc());
|
||||
verify("createBlackBox").with("something");
|
||||
}
|
||||
|
||||
@Test
|
||||
void should_able_to_mock_member_method() throws Exception {
|
||||
void should_mock_member_method() throws Exception {
|
||||
assertEquals("{ \"res\": \"mock_hello_MOCK_TAIL\"}", demoMock.outerFunc("hello"));
|
||||
verify("innerFunc").with("hello");
|
||||
verify("staticFunc").with();
|
||||
}
|
||||
|
||||
@Test
|
||||
void should_able_to_mock_common_method() {
|
||||
void should_mock_common_method() {
|
||||
assertEquals("trim_string__sub_string__false", demoMock.commonFunc());
|
||||
verify("trim").withTimes(1);
|
||||
verify("sub").withTimes(1);
|
||||
@ -94,13 +93,13 @@ class DemoMockTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
void should_able_to_mock_static_method() {
|
||||
void should_mock_static_method() {
|
||||
Assertions.assertEquals("not_secret_box", demoMock.getBox().get());
|
||||
verify("secretBox").withTimes(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
void should_able_to_get_source_method_name() throws Exception {
|
||||
void should_get_source_method_name() throws Exception {
|
||||
// synchronous
|
||||
assertEquals("mock_one_mock_others", demoMock.callerOne() + "_" + demoMock.callerTwo());
|
||||
// asynchronous
|
||||
@ -110,7 +109,7 @@ class DemoMockTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
void should_able_to_set_mock_context() throws Exception {
|
||||
void should_set_mock_context() throws Exception {
|
||||
MOCK_CONTEXT.put("case", "special_case");
|
||||
// synchronous
|
||||
assertEquals("mock_special", demoMock.callerOne());
|
||||
|
@ -0,0 +1,54 @@
|
||||
package com.alibaba.demo.basic;
|
||||
|
||||
import com.alibaba.demo.basic.model.omni.Child;
|
||||
import com.alibaba.demo.basic.model.omni.EnumChild;
|
||||
import com.alibaba.demo.basic.model.omni.GrandChild;
|
||||
import com.alibaba.demo.basic.model.omni.Parent;
|
||||
import com.alibaba.testable.core.tool.OmniAccessor;
|
||||
import com.alibaba.testable.core.tool.OmniConstructor;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
/**
|
||||
* 演示快速创建任意对象和使用路径访问成员
|
||||
* Demonstrate quick object construction and access members by path
|
||||
*/
|
||||
class DemoOmniMethodsTest {
|
||||
|
||||
@Test
|
||||
void should_construct_any_class() {
|
||||
// 所有基础类型初始化为默认数值
|
||||
GrandChild aGrandChild = OmniConstructor.newInstance(GrandChild.class);
|
||||
assertEquals(0, aGrandChild.getValue());
|
||||
|
||||
// 所有枚举类型初始化为第一个可选值
|
||||
Child aChild = OmniConstructor.newInstance(Child.class);
|
||||
assertEquals(EnumChild.VAL1, aChild.getEnumChild());
|
||||
|
||||
// 所有数组类型初始化为空数组
|
||||
// 所有子孙成员对象都会逐级初始化
|
||||
Parent aParent = OmniConstructor.newInstance(Parent.class);
|
||||
assertEquals(0, aParent.getChildren().length);
|
||||
assertEquals(0, aParent.getSubChild().getGrandChild().getValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
void should_get_any_member() {
|
||||
Parent demo = OmniConstructor.newInstance(Parent.class);
|
||||
|
||||
demo.getChild().setEnumChild(EnumChild.VAL2);
|
||||
assertEquals(EnumChild.VAL2, OmniAccessor.get(demo, "ec"));
|
||||
assertEquals(EnumChild.VAL2, OmniAccessor.get(demo, "{EnumChild}"));
|
||||
assertEquals(EnumChild.VAL2, OmniAccessor.get(demo, "c/ec"));
|
||||
|
||||
demo.setChildren(new Child[]{ new Child() });
|
||||
assertEquals(EnumChild.VAL1, OmniAccessor.get(demo, "cs[0]/ec"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void should_set_any_member() {
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -21,7 +21,7 @@ class DemoPrivateAccessTest {
|
||||
private DemoPrivateAccess demoPrivateAccess = new DemoPrivateAccess();
|
||||
|
||||
@Test
|
||||
void should_able_to_access_private_method() {
|
||||
void should_access_private_method() {
|
||||
List<String> list = new ArrayList<String>() {{ add("a"); add("b"); add("c"); }};
|
||||
assertEquals("member", demoPrivateAccess.privateFunc());
|
||||
assertEquals("member", PrivateAccessor.invoke(demoPrivateAccess, "privateFunc"));
|
||||
@ -30,7 +30,7 @@ class DemoPrivateAccessTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
void should_able_to_access_private_field() {
|
||||
void should_access_private_field() {
|
||||
demoPrivateAccess.count = 2;
|
||||
assertEquals(Integer.valueOf(2), demoPrivateAccess.count);
|
||||
|
||||
@ -39,7 +39,7 @@ class DemoPrivateAccessTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
void should_able_to_access_private_static_method() {
|
||||
void should_access_private_static_method() {
|
||||
assertEquals("static", DemoPrivateAccess.privateStaticFunc());
|
||||
assertEquals("static", PrivateAccessor.invokeStatic(DemoPrivateAccess.class, "privateStaticFunc"));
|
||||
assertEquals("hello + 1", DemoPrivateAccess.privateStaticFuncWithArgs("hello", 1));
|
||||
@ -47,7 +47,7 @@ class DemoPrivateAccessTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
void should_able_to_access_private_static_field() {
|
||||
void should_access_private_static_field() {
|
||||
DemoPrivateAccess.staticCount = 2;
|
||||
assertEquals(Integer.valueOf(2), DemoPrivateAccess.staticCount);
|
||||
|
||||
@ -56,7 +56,7 @@ class DemoPrivateAccessTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
void should_able_to_update_final_field() {
|
||||
void should_update_final_field() {
|
||||
demoPrivateAccess.pi = 4.13;
|
||||
assertEquals(Double.valueOf(4.13), demoPrivateAccess.pi);
|
||||
|
||||
@ -65,7 +65,7 @@ class DemoPrivateAccessTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
void should_able_to_use_null_parameter() {
|
||||
void should_use_null_parameter() {
|
||||
demoPrivateAccess.pi = null;
|
||||
assertNull(demoPrivateAccess.pi);
|
||||
assertEquals("null + 1", DemoPrivateAccess.privateStaticFuncWithArgs(null, 1));
|
||||
|
@ -72,19 +72,19 @@ class DemoTemplateTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
void should_able_to_mock_single_template_method() {
|
||||
void should_mock_single_template_method() {
|
||||
String res = demoTemplate.singleTemplateMethod();
|
||||
assertEquals("demo_mock_list", res);
|
||||
}
|
||||
|
||||
@Test
|
||||
void should_able_to_mock_double_template_method() {
|
||||
void should_mock_double_template_method() {
|
||||
String res = demoTemplate.doubleTemplateMethod();
|
||||
assertEquals("testable_mock_map", res);
|
||||
}
|
||||
|
||||
@Test
|
||||
void should_able_to_mock_new_template_method() {
|
||||
void should_mock_new_template_method() {
|
||||
Set<?> res = demoTemplate.newTemplateMethod();
|
||||
assertEquals(2, res.size());
|
||||
Iterator<?> iterator = res.stream().iterator();
|
||||
|
@ -15,7 +15,7 @@ public class OneToMultiSvcTest {
|
||||
private CSvc cSvc = new CSvc();
|
||||
|
||||
@Test
|
||||
public void should_able_to_test_multi_class_together() {
|
||||
public void should_test_multi_class_together() {
|
||||
assertEquals("a_mock", aSvc.demo("test"));
|
||||
assertEquals("b_mock", bSvc.demo("test"));
|
||||
assertEquals("c_mock", cSvc.demo("test"));
|
||||
|
@ -49,42 +49,42 @@ internal class DemoInheritTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun should_able_to_mock_call_sub_object_method_by_parent_object() {
|
||||
fun should_mock_call_sub_object_method_by_parent_object() {
|
||||
val box = demoInherit.putIntoBox() as BlackBox
|
||||
InvokeVerifier.verify("put_into_box").withTimes(1)
|
||||
Assertions.assertEquals("put_data_into_box", box.get())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun should_able_to_mock_call_sub_object_method_by_sub_object() {
|
||||
fun should_mock_call_sub_object_method_by_sub_object() {
|
||||
val box = demoInherit.putIntoBlackBox()
|
||||
InvokeVerifier.verify("put_into_blackbox").withTimes(1)
|
||||
Assertions.assertEquals("put_data_into_blackbox", box.get())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun should_able_to_mock_call_parent_object_method_by_parent_object() {
|
||||
fun should_mock_call_parent_object_method_by_parent_object() {
|
||||
val content = demoInherit.fromBox
|
||||
InvokeVerifier.verify("get_from_box").withTimes(1)
|
||||
Assertions.assertEquals("get_from_box", content)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun should_able_to_mock_call_parent_object_method_by_sub_object() {
|
||||
fun should_mock_call_parent_object_method_by_sub_object() {
|
||||
val content = demoInherit.fromBlackBox
|
||||
InvokeVerifier.verify("get_from_blackbox").withTimes(1)
|
||||
Assertions.assertEquals("get_from_blackbox", content)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun should_able_to_mock_call_interface_method_by_interface_object() {
|
||||
fun should_mock_call_interface_method_by_interface_object() {
|
||||
val color = demoInherit.colorViaColor
|
||||
InvokeVerifier.verify("get_color_from_color").withTimes(1)
|
||||
Assertions.assertEquals("color_from_color", color)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun should_able_to_mock_call_interface_method_by_sub_class_object() {
|
||||
fun should_mock_call_interface_method_by_sub_class_object() {
|
||||
val color = demoInherit.colorViaBox
|
||||
InvokeVerifier.verify("get_color_from_blackbox").withTimes(1)
|
||||
Assertions.assertEquals("color_from_blackbox", color)
|
||||
|
@ -19,7 +19,7 @@ internal class DemoInnerClassTest {
|
||||
|
||||
@Test
|
||||
@Throws(Exception::class)
|
||||
fun should_able_to_mock_invoke_inside_inner_class() {
|
||||
fun should_mock_invoke_inside_inner_class() {
|
||||
val demo = DemoInnerClass()
|
||||
Assertions.assertEquals("MockedCall", demo.callInnerDemo())
|
||||
Assertions.assertEquals("MockedCall", demo.callAnonymousInner())
|
||||
|
@ -64,26 +64,26 @@ internal class DemoMockTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun should_able_to_mock_new_object() {
|
||||
fun should_mock_new_object() {
|
||||
assertEquals("mock_something", demoMock.newFunc())
|
||||
verify("createBlackBox").with("something")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun should_able_to_mock_member_method() {
|
||||
fun should_mock_member_method() {
|
||||
assertEquals("{ \"res\": \"mock_hello_MOCK_TAIL\"}", demoMock.outerFunc("hello"))
|
||||
verify("innerFunc").with("hello")
|
||||
verify("staticFunc").with()
|
||||
}
|
||||
|
||||
// @Test
|
||||
// fun should_able_to_mock_method_in_companion_object() {
|
||||
// fun should_mock_method_in_companion_object() {
|
||||
// assertEquals("CALL_MOCK_TAIL", DemoMock.callStaticFunc())
|
||||
// verify("staticFunc").with()
|
||||
// }
|
||||
|
||||
@Test
|
||||
fun should_able_to_mock_common_method() {
|
||||
fun should_mock_common_method() {
|
||||
assertEquals("trim_string__sub_string__false", demoMock.commonFunc())
|
||||
verify("trim").withTimes(1)
|
||||
verify("sub").withTimes(1)
|
||||
@ -91,14 +91,14 @@ internal class DemoMockTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun should_able_to_mock_static_method() {
|
||||
fun should_mock_static_method() {
|
||||
assertEquals("White_not_secret_box", demoMock.getBox().get())
|
||||
verify("secretBox").withTimes(1)
|
||||
verify("createBox").withTimes(1)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun should_able_to_get_source_method_name() {
|
||||
fun should_get_source_method_name() {
|
||||
// synchronous
|
||||
assertEquals("mock_one_mock_others", demoMock.callerOne() + "_" + demoMock.callerTwo())
|
||||
// asynchronous
|
||||
@ -109,7 +109,7 @@ internal class DemoMockTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun should_able_to_get_test_case_name() {
|
||||
fun should_get_test_case_name() {
|
||||
MOCK_CONTEXT["case"] = "special_case"
|
||||
// synchronous
|
||||
assertEquals("mock_special", demoMock.callerOne())
|
||||
|
@ -13,32 +13,32 @@ internal class DemoPrivateAccessTest {
|
||||
private val demoPrivateAccess = DemoPrivateAccess()
|
||||
|
||||
@Test
|
||||
fun should_able_to_access_private_method() {
|
||||
fun should_access_private_method() {
|
||||
val list = listOf("a", "b", "c");
|
||||
assertEquals("abc + hello + 1", PrivateAccessor.invoke(demoPrivateAccess, "privateFunc", list, "hello", 1))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun should_able_to_access_private_field() {
|
||||
fun should_access_private_field() {
|
||||
PrivateAccessor.set(demoPrivateAccess, "count", 3)
|
||||
assertEquals(3, PrivateAccessor.get(demoPrivateAccess, "count"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun should_able_to_access_private_static_method() {
|
||||
fun should_access_private_static_method() {
|
||||
val list = listOf("a", "b", "c");
|
||||
assertEquals("hello + 1", PrivateAccessor.invokeStatic(DemoPrivateAccess::class.java, "privateStaticFunc", "hello", 1))
|
||||
assertEquals("abc * hello * 1", PrivateAccessor.invokeStatic(DemoPrivateAccess::class.java, "privateJvmStaticFunc", list, "hello", 1))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun should_able_to_access_private_static_field() {
|
||||
fun should_access_private_static_field() {
|
||||
PrivateAccessor.setStatic(DemoPrivateAccess::class.java, "staticCount", 3)
|
||||
assertEquals(3, PrivateAccessor.getStatic(DemoPrivateAccess::class.java, "staticCount"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun should_able_to_update_final_field() {
|
||||
fun should_update_final_field() {
|
||||
PrivateAccessor.set(demoPrivateAccess, "pi", 4.13)
|
||||
assertEquals(4.13, demoPrivateAccess.pi)
|
||||
}
|
||||
|
@ -40,19 +40,19 @@ internal class DemoTemplateTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun should_able_to_mock_single_template_method() {
|
||||
fun should_mock_single_template_method() {
|
||||
val res = demoTemplate.singleTemplateMethod()
|
||||
Assertions.assertEquals("demo_mock_list", res)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun should_able_to_mock_double_template_method() {
|
||||
fun should_mock_double_template_method() {
|
||||
val res = demoTemplate.doubleTemplateMethod()
|
||||
Assertions.assertEquals("testable_mock_map", res)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun should_able_to_mock_new_template_method() {
|
||||
fun should_mock_new_template_method() {
|
||||
val res = demoTemplate.newTemplateMethod()
|
||||
Assertions.assertEquals(2, res.size)
|
||||
val iterator = res.stream().iterator()
|
||||
|
@ -41,7 +41,7 @@ class PathUtilTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun should_able_to_mock_java_method_invoke_in_kotlin() {
|
||||
fun should_mock_java_method_invoke_in_kotlin() {
|
||||
PathUtil.deleteRecursively(File("/a/b/"))
|
||||
verify("listFiles").withTimes(2)
|
||||
verify("delete").withTimes(4)
|
||||
|
@ -13,7 +13,7 @@ class OneToMultiSvcTest {
|
||||
private val cSvc = CSvc()
|
||||
|
||||
@Test
|
||||
fun should_able_to_test_multi_class_together() {
|
||||
fun should_test_multi_class_together() {
|
||||
Assertions.assertEquals("a_mock", aSvc.demo("test"))
|
||||
Assertions.assertEquals("b_mock", bSvc.demo("test"))
|
||||
Assertions.assertEquals("c_mock", cSvc.demo("test"))
|
||||
|
@ -54,9 +54,9 @@ Executing the unit test again will print out the signatures of all mock methods,
|
||||
|
||||
```text
|
||||
[DIAGNOSE] Handling test class com/alibaba/testable/demo/basic/DemoMockTest
|
||||
[VERBOSE] Test case "should_able_to_mock_new_object"
|
||||
[VERBOSE] Test case "should_mock_new_object"
|
||||
... ...
|
||||
[VERBOSE] Test case "should_able_to_set_mock_context"
|
||||
[VERBOSE] Test case "should_set_mock_context"
|
||||
[DIAGNOSE] Found 6 test cases
|
||||
[DIAGNOSE] Handling mock class com/alibaba/testable/demo/basic/DemoMockTest$Mock
|
||||
[VERBOSE] Mock constructor "createBlackBox" as "com.alibaba.demo.basic.model.BlackBox(java.lang.String)"
|
||||
|
@ -19,7 +19,7 @@ public class DemoMockTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
void should_able_to_mock_member_method() throws Exception {
|
||||
void should_mock_member_method() throws Exception {
|
||||
assertEquals("hello_world", demoMock.outerFunc());
|
||||
verify("innerFunc").with("world");
|
||||
}
|
||||
@ -39,7 +39,7 @@ public class DemoMockTest {
|
||||
} // Add this line
|
||||
|
||||
@Test
|
||||
void should_able_to_mock_member_method() throws Exception {
|
||||
void should_mock_member_method() throws Exception {
|
||||
assertEquals("hello_world", demoMock.outerFunc());
|
||||
verify("innerFunc").with("world");
|
||||
}
|
||||
|
@ -67,7 +67,7 @@ private String substring(String self, int i, int j) {
|
||||
}
|
||||
```
|
||||
|
||||
For complete code examples, see the `should_able_to_mock_common_method()` test cases in the `java-demo` and `kotlin-demo` sample projects. (Because Kotlin has made magical changes to the String type, the method under test in the Kotlin example adds a layer of encapsulation to the `BlackBox` class)
|
||||
For complete code examples, see the `should_mock_common_method()` test cases in the `java-demo` and `kotlin-demo` sample projects. (Because Kotlin has made magical changes to the String type, the method under test in the Kotlin example adds a layer of encapsulation to the `BlackBox` class)
|
||||
|
||||
#### 2. Mock the member method of the class under test itself
|
||||
|
||||
@ -87,7 +87,7 @@ private String innerFunc(String text) {
|
||||
|
||||
Similarly, if the method in the above example needs to access the original tested object that initiated the call, it may not use the `targetClass` parameter, but when defining the mock method, add a parameter of type `DemoMock` to the first index of the method parameter list.
|
||||
|
||||
For complete code examples, see the `should_able_to_mock_member_method()` test case in the `java-demo` and `kotlin-demo` sample projects.
|
||||
For complete code examples, see the `should_mock_member_method()` test case in the `java-demo` and `kotlin-demo` sample projects.
|
||||
|
||||
#### 3. Mock static methods of any class
|
||||
|
||||
@ -102,7 +102,7 @@ private BlackBox secretBox() {
|
||||
}
|
||||
```
|
||||
|
||||
For complete code examples, see the `should_able_to_mock_static_method()` test case in the `java-demo` and `kotlin-demo` sample projects.
|
||||
For complete code examples, see the `should_mock_static_method()` test case in the `java-demo` and `kotlin-demo` sample projects.
|
||||
|
||||
#### 4. Mock `new` operation of any type
|
||||
|
||||
@ -123,7 +123,7 @@ private BlackBox createBlackBox(String text) {
|
||||
|
||||
> You can still use the `@MockMethod` annotation, and configure the `targetMethod` parameter value to `"<init>"`, and the rest is the same as above. The effect is the same as using the `@MockContructor` annotation
|
||||
|
||||
For complete code examples, see the `should_able_to_mock_new_object()` test case in the `java-demo` and `kotlin-demo` sample projects.
|
||||
For complete code examples, see the `should_mock_new_object()` test case in the `java-demo` and `kotlin-demo` sample projects.
|
||||
|
||||
#### 5. Identify different invocation source in mock method
|
||||
|
||||
@ -157,7 +157,7 @@ private Data mockDemo() {
|
||||
}
|
||||
```
|
||||
|
||||
For complete code examples, see the `should_able_to_get_source_method_name()` and `should_able_to_get_test_case_name()` test cases in the `java-demo` and `kotlin-demo` sample projects.
|
||||
For complete code examples, see the `should_get_source_method_name()` and `should_get_test_case_name()` test cases in the `java-demo` and `kotlin-demo` sample projects.
|
||||
|
||||
#### 6. Verify the sequence and parameters of the mock method being invoked
|
||||
|
||||
|
@ -59,9 +59,9 @@ class DemoTest {
|
||||
|
||||
```text
|
||||
[DIAGNOSE] Handling test class com/alibaba/testable/demo/basic/DemoMockTest
|
||||
[VERBOSE] Test case "should_able_to_mock_new_object"
|
||||
[VERBOSE] Test case "should_mock_new_object"
|
||||
... ...
|
||||
[VERBOSE] Test case "should_able_to_set_mock_context"
|
||||
[VERBOSE] Test case "should_set_mock_context"
|
||||
[DIAGNOSE] Found 6 test cases
|
||||
[DIAGNOSE] Handling mock class com/alibaba/testable/demo/basic/DemoMockTest$Mock
|
||||
[VERBOSE] Mock constructor "createBlackBox" as "com.alibaba.demo.basic.model.BlackBox(java.lang.String)"
|
||||
|
@ -19,7 +19,7 @@ public class DemoMockTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
void should_able_to_mock_member_method() throws Exception {
|
||||
void should_mock_member_method() throws Exception {
|
||||
assertEquals("hello_world", demoMock.outerFunc());
|
||||
verify("innerFunc").with("world");
|
||||
}
|
||||
@ -39,7 +39,7 @@ public class DemoMockTest {
|
||||
} // 增加此行
|
||||
|
||||
@Test
|
||||
void should_able_to_mock_member_method() throws Exception {
|
||||
void should_mock_member_method() throws Exception {
|
||||
assertEquals("hello_world", demoMock.outerFunc());
|
||||
verify("innerFunc").with("world");
|
||||
}
|
||||
|
@ -67,7 +67,7 @@ private String substring(String self, int i, int j) {
|
||||
}
|
||||
```
|
||||
|
||||
完整代码示例见`java-demo`和`kotlin-demo`示例项目中的`should_able_to_mock_common_method()`测试用例。(由于Kotlin对String类型进行了魔改,故Kotlin示例中将被测方法在`BlackBox`类里加了一层封装)
|
||||
完整代码示例见`java-demo`和`kotlin-demo`示例项目中的`should_mock_common_method()`测试用例。(由于Kotlin对String类型进行了魔改,故Kotlin示例中将被测方法在`BlackBox`类里加了一层封装)
|
||||
|
||||
#### 2. 覆写被测类自身的成员方法
|
||||
|
||||
@ -87,7 +87,7 @@ private String innerFunc(String text) {
|
||||
|
||||
同样的,上述示例中的方法如需访问发起调用的原始被测对象,也可不使用`targetClass`参数,而是在定义Mock方法时,在方法参数列表首位加一个类型为`DemoMock`的参数(名字随意)。
|
||||
|
||||
完整代码示例见`java-demo`和`kotlin-demo`示例项目中的`should_able_to_mock_member_method()`测试用例。
|
||||
完整代码示例见`java-demo`和`kotlin-demo`示例项目中的`should_mock_member_method()`测试用例。
|
||||
|
||||
#### 3. 覆写任意类的静态方法
|
||||
|
||||
@ -104,7 +104,7 @@ private BlackBox secretBox() {
|
||||
|
||||
对于静态方法的Mock,通常不使用方法参数列表的首位加参数来表示目标类型。但这种方法也依然适用,只是实际传入的第一个参数值将始终是`null`。
|
||||
|
||||
完整代码示例见`java-demo`和`kotlin-demo`示例项目中的`should_able_to_mock_static_method()`测试用例。
|
||||
完整代码示例见`java-demo`和`kotlin-demo`示例项目中的`should_mock_static_method()`测试用例。
|
||||
|
||||
#### 4. 覆写任意类的new操作
|
||||
|
||||
@ -123,7 +123,7 @@ private BlackBox createBlackBox(String text) {
|
||||
}
|
||||
```
|
||||
|
||||
完整代码示例见`java-demo`和`kotlin-demo`示例项目中的`should_able_to_mock_new_object()`测试用例。
|
||||
完整代码示例见`java-demo`和`kotlin-demo`示例项目中的`should_mock_new_object()`测试用例。
|
||||
|
||||
#### 5. 在Mock方法中区分调用来源
|
||||
|
||||
@ -157,7 +157,7 @@ private Data mockDemo() {
|
||||
}
|
||||
```
|
||||
|
||||
完整代码示例见`java-demo`和`kotlin-demo`示例项目中的`should_able_to_get_source_method_name()`和`should_able_to_get_test_case_name()`测试用例。
|
||||
完整代码示例见`java-demo`和`kotlin-demo`示例项目中的`should_get_source_method_name()`和`should_get_test_case_name()`测试用例。
|
||||
|
||||
#### 6. 验证Mock方法被调用的顺序和参数
|
||||
|
||||
|
@ -7,12 +7,12 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
class ClassUtilTest {
|
||||
|
||||
@Test
|
||||
void should_able_to_convert_class_name() {
|
||||
void should_convert_class_name() {
|
||||
assertEquals("Ljava/lang/String;", ClassUtil.toByteCodeClassName("java.lang.String"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void should_able_to_fit_companion_class_name() {
|
||||
void should_fit_companion_class_name() {
|
||||
assertEquals("com/intellij/rt/debugger/agent/CaptureAgent$ParamKeyProvider",
|
||||
ClassUtil.fitCompanionClassName("com/intellij/rt/debugger/agent/CaptureAgent$ParamKeyProvider"));
|
||||
assertEquals("com/alibaba/testable/demo/BlackBox",
|
||||
|
@ -7,7 +7,7 @@ import static org.junit.jupiter.api.Assertions.*;
|
||||
class CollectionUtilTest {
|
||||
|
||||
@Test
|
||||
void should_able_to_check_collection_contains_any_element() {
|
||||
void should_check_collection_contains_any_element() {
|
||||
assertTrue(CollectionUtil.containsAny(
|
||||
CollectionUtil.listOf("a", "b"), CollectionUtil.listOf("b", "c")
|
||||
));
|
||||
|
@ -8,7 +8,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
class MethodUtilTest {
|
||||
|
||||
@Test
|
||||
void should_able_to_get_parameter_count() {
|
||||
void should_get_parameter_count() {
|
||||
assertEquals(0, MethodUtil.getParameterTypes("()V").size());
|
||||
assertEquals(1, MethodUtil.getParameterTypes("(Ljava/lang/String;)V").size());
|
||||
assertEquals(6, MethodUtil.getParameterTypes("(Ljava/lang/String;IDLjava/lang/String;ZLjava/net/URL;)V").size());
|
||||
@ -17,13 +17,13 @@ class MethodUtilTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
void should_able_to_extract_parameter() {
|
||||
void should_extract_parameter() {
|
||||
assertEquals("", MethodUtil.extractParameters("()I"));
|
||||
assertEquals("Ljava/lang/String;", MethodUtil.extractParameters("(Ljava/lang/String;)I"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void should_able_to_get_return_type() {
|
||||
void should_get_return_type() {
|
||||
assertEquals("V", MethodUtil.getReturnType("(Ljava/lang/String;)V"));
|
||||
assertEquals("I", MethodUtil.getReturnType("(Ljava/lang/String;)I"));
|
||||
assertEquals("[I", MethodUtil.getReturnType("(Ljava/lang/String;)[I"));
|
||||
@ -32,14 +32,14 @@ class MethodUtilTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
void should_able_to_get_first_parameter() {
|
||||
void should_get_first_parameter() {
|
||||
assertEquals("Ljava/lang/String;", MethodUtil.getFirstParameter("(Ljava/lang/String;Ljava/lang/Object;I)V"));
|
||||
assertEquals("Ljava/lang/String;", MethodUtil.getFirstParameter("(Ljava/lang/String;)V"));
|
||||
assertEquals("", MethodUtil.getFirstParameter("()V"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void should_able_to_convert_bytecode_parameters() {
|
||||
void should_convert_bytecode_parameters() {
|
||||
assertEquals("", PrivateAccessor.invokeStatic(MethodUtil.class, "toJavaParameterDesc", ""));
|
||||
assertEquals("void", PrivateAccessor.invokeStatic(MethodUtil.class, "toJavaParameterDesc", "V"));
|
||||
assertEquals("int, long", PrivateAccessor.invokeStatic(MethodUtil.class, "toJavaParameterDesc", "IJ"));
|
||||
|
@ -7,7 +7,7 @@ import static org.junit.jupiter.api.Assertions.*;
|
||||
class StringUtilTest {
|
||||
|
||||
@Test
|
||||
void should_able_to_repeat_text() {
|
||||
void should_repeat_text() {
|
||||
assertEquals("", StringUtil.repeat("abc", 0));
|
||||
assertEquals("abc", StringUtil.repeat("abc", 1));
|
||||
assertEquals("abcabcabc", StringUtil.repeat("abc", 3));
|
||||
|
@ -15,6 +15,8 @@ public class PrivateAccessor {
|
||||
|
||||
private static final String KOTLIN_COMPANION_FIELD = "Companion";
|
||||
|
||||
private PrivateAccessor() {}
|
||||
|
||||
/**
|
||||
* 读取任意类的私有字段
|
||||
* @param ref 目标对象
|
||||
|
@ -0,0 +1,26 @@
|
||||
package com.alibaba.testable.core.exception;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
|
||||
/**
|
||||
* @author flin
|
||||
*/
|
||||
public class ClassConstructionException extends RuntimeException {
|
||||
|
||||
public ClassConstructionException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public ClassConstructionException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
private static Throwable getRootCause(Throwable cause) {
|
||||
if (cause instanceof InvocationTargetException) {
|
||||
return ((InvocationTargetException)cause).getTargetException();
|
||||
} else {
|
||||
return cause;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -8,6 +8,7 @@ import java.lang.reflect.Array;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static com.alibaba.testable.core.constant.ConstPool.SLASH;
|
||||
@ -27,26 +28,28 @@ public class OmniAccessor {
|
||||
private static final String BRACKET_START = "[";
|
||||
private static final String BRACKET_END = "]";
|
||||
|
||||
private OmniAccessor() {}
|
||||
|
||||
/**
|
||||
* 获取第一个符合搜索路径的成员
|
||||
* @param target 目标对象
|
||||
*
|
||||
* @param target 目标对象
|
||||
* @param queryPath 搜索路径
|
||||
* @param clazz 目标成员类型
|
||||
* @return 返回目标成员,若不存在则返回null
|
||||
*/
|
||||
public static <T> T getFirst(Object target, String queryPath, Class<T> clazz) {
|
||||
List<T> values = get(target, queryPath, clazz);
|
||||
return values.isEmpty() ? null : values.get(0);
|
||||
public static <T> T getFirst(Object target, String queryPath) {
|
||||
T[] values = get(target, queryPath);
|
||||
return values.length == 0 ? null : values[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有符合搜索路径的成员
|
||||
* @param target 目标对象
|
||||
*
|
||||
* @param target 目标对象
|
||||
* @param queryPath 搜索路径
|
||||
* @param clazz 目标成员类型
|
||||
* @return 返回所有匹配的成员
|
||||
*/
|
||||
public static <T> List<T> get(Object target, String queryPath, Class<T> clazz) {
|
||||
public static <T> T[] get(Object target, String queryPath) {
|
||||
List<T> values = new ArrayList<T>();
|
||||
for (String memberPath : MEMBER_INDEXES.getOrElse(target.getClass(), generateMemberIndex(target.getClass()))) {
|
||||
if (memberPath.matches(toPattern(queryPath))) {
|
||||
@ -62,14 +65,15 @@ public class OmniAccessor {
|
||||
}
|
||||
}
|
||||
}
|
||||
return values;
|
||||
return (T[])values.toArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* 为符合搜索路径的成员赋值
|
||||
* @param target 目标对象
|
||||
*
|
||||
* @param target 目标对象
|
||||
* @param queryPath 搜索路径
|
||||
* @param value 新的值
|
||||
* @param value 新的值
|
||||
* @return 实际影响的成员个数
|
||||
*/
|
||||
public static int set(Object target, String queryPath, Object value) {
|
||||
@ -97,6 +101,9 @@ public class OmniAccessor {
|
||||
}
|
||||
|
||||
private static List<String> generateMemberIndex(String basePath, Class<?> clazz) {
|
||||
if (clazz.isEnum()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
List<Field> fields = TypeUtil.getAllFields(clazz);
|
||||
List<String> paths = new ArrayList<String>();
|
||||
for (Field f : fields) {
|
||||
@ -155,12 +162,11 @@ public class OmniAccessor {
|
||||
private static Object getByPath(Object target, String memberPath, String queryPath)
|
||||
throws NoSuchFieldException, IllegalAccessException {
|
||||
String[] memberSegments = memberPath.split(SLASH);
|
||||
String[] querySegments = queryPath.split(SLASH);
|
||||
String[] querySegments = calculateFullQueryPath(queryPath.split(SLASH), memberSegments);
|
||||
Object obj = target;
|
||||
String name;
|
||||
int nth;
|
||||
Field field;
|
||||
assert memberSegments.length == querySegments.length;
|
||||
for (int i = 0; i < memberSegments.length; i++) {
|
||||
name = memberSegments[i].substring(0, memberSegments[i].indexOf(BRACE_START));
|
||||
nth = extraIndexFromQuery(querySegments[i]);
|
||||
@ -176,6 +182,21 @@ public class OmniAccessor {
|
||||
return obj;
|
||||
}
|
||||
|
||||
private static String[] calculateFullQueryPath(String[] querySegments, String[] memberSegments) {
|
||||
assert memberSegments.length >= querySegments.length;
|
||||
;
|
||||
if (memberSegments.length > querySegments.length) {
|
||||
String[] fullQuerySegments = new String[memberSegments.length];
|
||||
for (int i = 0; i < querySegments.length; i++) {
|
||||
fullQuerySegments[i] = "";
|
||||
}
|
||||
System.arraycopy(querySegments, 0, fullQuerySegments, querySegments.length,
|
||||
memberSegments.length - querySegments.length);
|
||||
return fullQuerySegments;
|
||||
}
|
||||
return querySegments;
|
||||
}
|
||||
|
||||
private static void setByPathSegment(Object target, String memberSegment, String querySegment, Object value)
|
||||
throws IllegalAccessException {
|
||||
String name = memberSegment.substring(0, memberSegment.indexOf(BRACE_START));
|
||||
|
@ -1,5 +1,6 @@
|
||||
package com.alibaba.testable.core.tool;
|
||||
|
||||
import com.alibaba.testable.core.exception.ClassConstructionException;
|
||||
import com.alibaba.testable.core.model.Null;
|
||||
import com.alibaba.testable.core.util.TypeUtil;
|
||||
|
||||
@ -10,6 +11,8 @@ import java.lang.reflect.*;
|
||||
*/
|
||||
public class OmniConstructor {
|
||||
|
||||
private OmniConstructor() {}
|
||||
|
||||
public static <T> T newInstance(Class<T> clazz) {
|
||||
try {
|
||||
if (clazz.isPrimitive()) {
|
||||
@ -25,15 +28,15 @@ public class OmniConstructor {
|
||||
}
|
||||
return newObject(clazz);
|
||||
} catch (NoSuchMethodException e) {
|
||||
return null;
|
||||
throw new ClassConstructionException("Failed to find constructor", e);
|
||||
} catch (IllegalAccessException e) {
|
||||
return null;
|
||||
} catch (InstantiationException e) {
|
||||
return null;
|
||||
throw new ClassConstructionException("Failed to access constructor", e);
|
||||
} catch (InvocationTargetException e) {
|
||||
return null;
|
||||
throw new ClassConstructionException("Failed to invoke constructor", e);
|
||||
} catch (InstantiationException e) {
|
||||
throw new ClassConstructionException("Failed to complete construction", e);
|
||||
} catch (ClassCastException e) {
|
||||
return null;
|
||||
throw new ClassConstructionException("Unexpected type", e);
|
||||
}
|
||||
}
|
||||
|
||||
@ -88,15 +91,6 @@ public class OmniConstructor {
|
||||
return null;
|
||||
}
|
||||
|
||||
private static boolean isJavaAgentEnabled(Class<?> clazz) {
|
||||
try {
|
||||
clazz.getDeclaredConstructor(Null.class);
|
||||
} catch (NoSuchMethodException e) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static Object newInstance(Constructor<?> constructor)
|
||||
throws InstantiationException, IllegalAccessException, InvocationTargetException {
|
||||
Class<?>[] types = constructor.getParameterTypes();
|
||||
|
@ -33,24 +33,24 @@ class OmniAccessorTest {
|
||||
|
||||
@Test
|
||||
void should_match_pattern() {
|
||||
assertTrue("abc{Abc}".matches("abc\\{[^}]+\\}"));
|
||||
assertTrue("abc{Abc}".matches("[^{]+\\{Abc\\}"));
|
||||
assertTrue("abc{Abc[]}/xyz{Xyz[]}".matches("[^{]+\\{Abc\\[\\]\\}/[^{]+\\{Xyz\\[\\]\\}"));
|
||||
assertTrue("abc{Abc}/xyz{Xyz}/demo{Demo}".matches("abc\\{[^}]+\\}/[^{]+\\{Xyz\\}/demo\\{[^}]+\\}"));
|
||||
assertTrue("/abc{Abc}".matches(".*/abc\\{[^}]+\\}"));
|
||||
assertTrue("/abc{Abc}".matches(".*/[^{]+\\{Abc\\}"));
|
||||
assertTrue("/abc{Abc[]}/xyz{Xyz[]}".matches(".*/[^{]+\\{Abc\\[\\]\\}/[^{]+\\{Xyz\\[\\]\\}"));
|
||||
assertTrue("/abc{Abc}/xyz{Xyz}/demo{Demo}".matches(".*/abc\\{[^}]+\\}/[^{]+\\{Xyz\\}/demo\\{[^}]+\\}"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void should_to_pattern() {
|
||||
assertEquals("", PrivateAccessor.<String>invokeStatic(OmniAccessor.class, "toPattern", ""));
|
||||
assertEquals("abc\\{[^}]+\\}", PrivateAccessor.<String>invokeStatic(OmniAccessor.class, "toPattern", "abc"));
|
||||
assertEquals("[^{]+\\{Abc\\}", PrivateAccessor.<String>invokeStatic(OmniAccessor.class, "toPattern", "{Abc}"));
|
||||
assertEquals("abc\\{[^}]+\\}/xyz\\{[^}]+\\}", PrivateAccessor.<String>invokeStatic(OmniAccessor.class, "toPattern", "abc/xyz"));
|
||||
assertEquals("[^{]+\\{Abc\\}/xyz\\{[^}]+\\}", PrivateAccessor.<String>invokeStatic(OmniAccessor.class, "toPattern", "{Abc}/xyz"));
|
||||
assertEquals("abc\\{[^}]+\\}/[^{]+\\{Xyz\\}", PrivateAccessor.<String>invokeStatic(OmniAccessor.class, "toPattern", "abc/{Xyz}"));
|
||||
assertEquals("[^{]+\\{Abc\\}/[^{]+\\{Xyz\\}", PrivateAccessor.<String>invokeStatic(OmniAccessor.class, "toPattern", "{Abc}/{Xyz}"));
|
||||
assertEquals("[^{]+\\{Abc\\[\\]\\}/[^{]+\\{Xyz\\[\\]\\}", PrivateAccessor.<String>invokeStatic(OmniAccessor.class, "toPattern", "{Abc[]}/{Xyz[]}"));
|
||||
assertEquals("abc\\{[^}]+\\}/[^{]+\\{Xyz\\[\\]\\}", PrivateAccessor.<String>invokeStatic(OmniAccessor.class, "toPattern", "abc[1]/{Xyz[]}[2]"));
|
||||
assertEquals("abc\\{[^}]+\\}/[^{]+\\{Xyz\\}/demo\\{[^}]+\\}", PrivateAccessor.<String>invokeStatic(OmniAccessor.class, "toPattern", "abc/{Xyz}/demo"));
|
||||
assertEquals(".*/", PrivateAccessor.<String>invokeStatic(OmniAccessor.class, "toPattern", ""));
|
||||
assertEquals(".*/abc\\{[^}]+\\}", PrivateAccessor.<String>invokeStatic(OmniAccessor.class, "toPattern", "abc"));
|
||||
assertEquals(".*/[^{]+\\{Abc\\}", PrivateAccessor.<String>invokeStatic(OmniAccessor.class, "toPattern", "{Abc}"));
|
||||
assertEquals(".*/abc\\{[^}]+\\}/xyz\\{[^}]+\\}", PrivateAccessor.<String>invokeStatic(OmniAccessor.class, "toPattern", "abc/xyz"));
|
||||
assertEquals(".*/[^{]+\\{Abc\\}/xyz\\{[^}]+\\}", PrivateAccessor.<String>invokeStatic(OmniAccessor.class, "toPattern", "{Abc}/xyz"));
|
||||
assertEquals(".*/abc\\{[^}]+\\}/[^{]+\\{Xyz\\}", PrivateAccessor.<String>invokeStatic(OmniAccessor.class, "toPattern", "abc/{Xyz}"));
|
||||
assertEquals(".*/[^{]+\\{Abc\\}/[^{]+\\{Xyz\\}", PrivateAccessor.<String>invokeStatic(OmniAccessor.class, "toPattern", "{Abc}/{Xyz}"));
|
||||
assertEquals(".*/[^{]+\\{Abc\\[\\]\\}/[^{]+\\{Xyz\\[\\]\\}", PrivateAccessor.<String>invokeStatic(OmniAccessor.class, "toPattern", "{Abc[]}/{Xyz[]}"));
|
||||
assertEquals(".*/abc\\{[^}]+\\}/[^{]+\\{Xyz\\[\\]\\}", PrivateAccessor.<String>invokeStatic(OmniAccessor.class, "toPattern", "abc[1]/{Xyz[]}[2]"));
|
||||
assertEquals(".*/abc\\{[^}]+\\}/[^{]+\\{Xyz\\}/demo\\{[^}]+\\}", PrivateAccessor.<String>invokeStatic(OmniAccessor.class, "toPattern", "abc/{Xyz}/demo"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -71,21 +71,33 @@ class OmniAccessorTest {
|
||||
assertEquals("xyz", PrivateAccessor.<String>invokeStatic(OmniAccessor.class, "toChild", "/abc/def/xyz"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void should_get_full_query_segments() {
|
||||
String[] querySegments = new String[] { "c", "d" };
|
||||
String[] memberSegments = new String[] { "a{A}", "b{B}", "c{C}", "d{D}" };
|
||||
String[] fullQuerySegments = PrivateAccessor.invokeStatic(OmniAccessor.class, "calculateFullQueryPath", querySegments, memberSegments);
|
||||
assertEquals(4, fullQuerySegments.length);
|
||||
assertEquals("", fullQuerySegments[0]);
|
||||
assertEquals("", fullQuerySegments[1]);
|
||||
assertEquals("c", fullQuerySegments[2]);
|
||||
assertEquals("d", fullQuerySegments[3]);
|
||||
}
|
||||
|
||||
@Test
|
||||
void should_get_by_path() {
|
||||
DemoParent parent = prepareParentObject();
|
||||
Object obj = PrivateAccessor.<String>invokeStatic(OmniAccessor.class, "getByPath", parent, "c{DemoChild}/gc{DemoGrandChild}", "c/gc");
|
||||
Object obj = PrivateAccessor.<String>invokeStatic(OmniAccessor.class, "getByPath", parent, "/c{DemoChild}/gc{DemoGrandChild}", "c/gc");
|
||||
assertTrue(obj instanceof DemoGrandChild);
|
||||
assertEquals(0, ((DemoGrandChild)obj).get());
|
||||
PrivateAccessor.set(parent.c, "gcs", new DemoGrandChild[] { new DemoGrandChild(4), new DemoGrandChild(6) });
|
||||
obj = PrivateAccessor.<String>invokeStatic(OmniAccessor.class, "getByPath", parent, "c{DemoChild}/gcs{DemoGrandChild[]}", "c/gcs");
|
||||
obj = PrivateAccessor.<String>invokeStatic(OmniAccessor.class, "getByPath", parent, "/c{DemoChild}/gcs{DemoGrandChild[]}", "c/gcs");
|
||||
assertTrue(obj instanceof DemoGrandChild[]);
|
||||
assertEquals(2, ((DemoGrandChild[])obj).length);
|
||||
obj = PrivateAccessor.<String>invokeStatic(OmniAccessor.class, "getByPath", parent, "c{DemoChild}/gcs{DemoGrandChild[]}", "c/gcs[1]");
|
||||
obj = PrivateAccessor.<String>invokeStatic(OmniAccessor.class, "getByPath", parent, "/c{DemoChild}/gcs{DemoGrandChild[]}", "c/gcs[1]");
|
||||
assertTrue(obj instanceof DemoGrandChild);
|
||||
assertEquals(6, ((DemoGrandChild)obj).get());
|
||||
parent.cs = new DemoChild[] { null, prepareChildObject() };
|
||||
obj = PrivateAccessor.<String>invokeStatic(OmniAccessor.class, "getByPath", parent, "cs{DemoChild[]}/gcs{DemoGrandChild[]}/i{int}", "c[1]/gcs[1]/i");
|
||||
obj = PrivateAccessor.<String>invokeStatic(OmniAccessor.class, "getByPath", parent, "/cs{DemoChild[]}/gcs{DemoGrandChild[]}/i{int}", "c[1]/gcs[1]/i");
|
||||
assertEquals(3, obj);
|
||||
}
|
||||
|
||||
|
@ -8,7 +8,7 @@ import static org.junit.jupiter.api.Assertions.*;
|
||||
class MockAssociationUtilTest {
|
||||
|
||||
@Test
|
||||
void should_able_to_associate_by_inner_mock_class() {
|
||||
void should_associate_by_inner_mock_class() {
|
||||
assertTrue((Boolean)PrivateAccessor.invokeStatic(MockAssociationUtil.class, "isAssociatedByInnerMockClass",
|
||||
"com.alibaba.testable.DemoTest", "com.alibaba.testable.DemoTest$Mock"));
|
||||
assertFalse((Boolean)PrivateAccessor.invokeStatic(MockAssociationUtil.class, "isAssociatedByInnerMockClass",
|
||||
@ -16,7 +16,7 @@ class MockAssociationUtilTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
void should_able_to_associate_by_outer_mock_class() {
|
||||
void should_associate_by_outer_mock_class() {
|
||||
assertTrue((Boolean)PrivateAccessor.invokeStatic(MockAssociationUtil.class, "isAssociatedByOuterMockClass",
|
||||
"com.alibaba.testable.DemoTest", "com.alibaba.testable.DemoMock"));
|
||||
assertFalse((Boolean)PrivateAccessor.invokeStatic(MockAssociationUtil.class, "isAssociatedByOuterMockClass",
|
||||
|
@ -10,7 +10,7 @@ import static org.junit.jupiter.api.Assertions.*;
|
||||
class StringUtilTest {
|
||||
|
||||
@Test
|
||||
void should_able_to_join_string() {
|
||||
void should_join_string() {
|
||||
List<String> list = new ArrayList<String>(4);
|
||||
list.add("a");
|
||||
list.add("b");
|
||||
|
Loading…
Reference in New Issue
Block a user