add demo module

This commit is contained in:
金戟 2020-10-20 21:08:47 +08:00
parent 42a5c501fd
commit 770aca8a00
17 changed files with 636 additions and 9 deletions

View File

@ -7,11 +7,8 @@ import com.alibaba.testable.core.constant.ConstPool;
*/
public class TestableUtil {
public static String sourceMemberMethodName(Object testClassRef) {
return sourceMemberMethodName(testClassRef.getClass());
}
public static String sourceMemberMethodName(Class<?> testClass) {
public static String currentSourceMethodName(Object testClassRef) {
Class<?> testClass = testClassRef.getClass();
StackTraceElement[] stack = getMainThread().getStackTrace();
String testClassName = getRealClassName(testClass);
String sourceClassName = testClassName.substring(0, testClassName.length() - ConstPool.TEST_POSTFIX.length());
@ -24,10 +21,7 @@ public class TestableUtil {
}
public static String currentTestCaseName(Object testClassRef) {
return currentTestCaseName(testClassRef.getClass());
}
public static String currentTestCaseName(Class<?> testClass) {
Class<?> testClass = testClassRef.getClass();
StackTraceElement[] stack = getMainThread().getStackTrace();
String testClassName = getRealClassName(testClass);
for (int i = stack.length - 1; i >= 0; i--) {

93
demo/java-demo/pom.xml Normal file
View File

@ -0,0 +1,93 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.4.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.alibaba.testable</groupId>
<artifactId>java-demo</artifactId>
<version>1.0.0-SNAPSHOT</version>
<name>java-demo</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
<testable.version>0.1.0-SNAPSHOT</testable.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.testable</groupId>
<artifactId>core</artifactId>
<version>${testable.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
<exclusion>
<groupId>org.ow2.asm</groupId>
<artifactId>asm</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<!-- <argLine>@{argLine} -javaagent:${project.build.directory}/test-classes/testable-agent.jar</argLine>-->
<argLine>@{argLine} -javaagent:${settings.localRepository}/com/alibaba/testable/agent/${testable.version}/agent-${testable.version}.jar</argLine>
</configuration>
</plugin>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.6</version>
<executions>
<execution>
<id>prepare-agent</id>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>report</id>
<phase>prepare-package</phase>
<goals>
<goal>report</goal>
</goals>
<configuration>
<dataFile>target/jacoco.exec</dataFile>
<outputDirectory>target/jacoco-ut</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,15 @@
package com.alibaba.testable.demo;
public class BlackBox {
private String data;
public BlackBox(String data) {
this.data = data;
}
public String callMe() {
return data;
}
}

View File

@ -0,0 +1,12 @@
package com.alibaba.testable.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}

View File

@ -0,0 +1,66 @@
package com.alibaba.testable.demo;
import org.springframework.stereotype.Service;
import sun.net.www.http.HttpClient;
import java.net.URL;
@Service
public class DemoService {
private int count;
/**
* Target 1 - private method
*/
private String privateFunc(String s, int i) {
return s + " - " + i;
}
/**
* Target 2 - method with private field access
*/
public String privateFieldAccessFunc() {
count += 2;
return String.valueOf(count);
}
/**
* Target 3 - method with new operation
*/
public String newFunc() {
BlackBox component = new BlackBox("something");
return component.callMe();
}
/**
* Target 4 - method with member method invoke
*/
public String outerFunc(String s) throws Exception {
return "{ \"res\": \"" + innerFunc(s) + "\"}";
}
/**
* Target 5 - method with common method invoke
*/
public String commonFunc() {
return "anything".trim() + "__" + "anything".substring(1, 2) + "__" + "abc".startsWith("ab");
}
public String callerOne() {
return callFromDifferentMethod();
}
public String callerTwo() {
return callFromDifferentMethod();
}
private String innerFunc(String s) throws Exception {
return HttpClient.New(new URL("http:/xxx/" + s)).getURLFile();
}
private String callFromDifferentMethod() {
return "realOne";
}
}

View File

@ -0,0 +1 @@

View File

@ -0,0 +1,13 @@
package com.alibaba.testable.demo;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class DemoApplicationTests {
@Test
void contextLoads() {
}
}

View File

@ -0,0 +1,104 @@
package com.alibaba.testable.demo;
import com.alibaba.testable.core.accessor.PrivateAccessor;
import com.alibaba.testable.core.annotation.EnableTestable;
import com.alibaba.testable.core.annotation.TestableInject;
import com.alibaba.testable.core.util.TestableUtil;
import org.junit.jupiter.api.Test;
import java.util.concurrent.Callable;
import static org.junit.jupiter.api.Assertions.assertEquals;
@EnableTestable
class DemoServiceTest {
@TestableInject
private BlackBox createBlackBox(String text) {
return new BlackBox("mock_" + text);
}
@TestableInject
private String innerFunc(String text) {
return "mock_" + text;
}
@TestableInject(targetClass="java.lang.String")
private String trim(String self) {
return "trim_string";
}
@TestableInject(targetClass="java.lang.String", targetMethod = "substring")
private String sub(String self, int i, int j) {
return "sub_string";
}
@TestableInject(targetClass="java.lang.String")
private boolean startsWith(String self, String s) {
return false;
}
@TestableInject
private String callFromDifferentMethod() {
switch (TestableUtil.currentSourceMethodName(this)) {
case "callerOne": return "mock_one";
default: return "mock_others";
}
}
private DemoService demoService = new DemoService();
@Test
void should_able_to_test_private_method() throws Exception {
assertEquals("hello - 1", demoService.privateFunc("hello", 1));
assertEquals("hello - 1", PrivateAccessor.invoke(demoService, "privateFunc", "hello", 1));
}
@Test
void should_able_to_test_private_field() throws Exception {
demoService.count = 2;
assertEquals("4", demoService.privateFieldAccessFunc());
PrivateAccessor.set(demoService, "count", 3);
assertEquals("5", demoService.privateFieldAccessFunc());
assertEquals(new Integer(5), PrivateAccessor.get(demoService, "count"));
}
@Test
void should_able_to_test_new_object() throws Exception {
assertEquals("mock_something", demoService.newFunc());
}
@Test
void should_able_to_test_member_method() throws Exception {
assertEquals("{ \"res\": \"mock_hello\"}", demoService.outerFunc("hello"));
}
@Test
void should_able_to_test_common_method() throws Exception {
assertEquals("trim_string__sub_string__false", demoService.commonFunc());
}
@Test
void should_able_to_get_source_method_name() throws Exception {
assertEquals("mock_one", demoService.callerOne());
assertEquals("mock_others", demoService.callerTwo());
assertEquals("mock_one_mock_others", new Callable<String>() {
@Override
public String call() {
return demoService.callerOne() + "_" + demoService.callerTwo();
}
}.call());
}
@Test
void should_able_to_get_test_case_name() throws Exception {
assertEquals("should_able_to_get_test_case_name", TestableUtil.currentTestCaseName(this));
assertEquals("should_able_to_get_test_case_name", new Callable<String>() {
@Override
public String call() {
return TestableUtil.currentTestCaseName(this);
}
}.call());
}
}

122
demo/kotlin-demo/pom.xml Normal file
View File

@ -0,0 +1,122 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.4.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.alibaba.testable</groupId>
<artifactId>kotlin-demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>kotlin-demo</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
<kotlin.version>1.3.72</kotlin.version>
<testable.version>0.1.0-SNAPSHOT</testable.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-reflect</artifactId>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib-jdk8</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.testable</groupId>
<artifactId>core</artifactId>
<version>${testable.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build>
<sourceDirectory>${project.basedir}/src/main/kotlin</sourceDirectory>
<testSourceDirectory>${project.basedir}/src/test/kotlin</testSourceDirectory>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<argLine>@{argLine} -javaagent:${settings.localRepository}/com/alibaba/testable/agent/${testable.version}/agent-${testable.version}.jar</argLine>
</configuration>
</plugin>
<plugin>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-plugin</artifactId>
<configuration>
<args>
<arg>-Xjsr305=strict</arg>
</args>
<compilerPlugins>
<plugin>spring</plugin>
</compilerPlugins>
</configuration>
<dependencies>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-allopen</artifactId>
<version>${kotlin.version}</version>
</dependency>
</dependencies>
</plugin>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.6</version>
<executions>
<execution>
<id>prepare-agent</id>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>report</id>
<phase>prepare-package</phase>
<goals>
<goal>report</goal>
</goals>
<configuration>
<dataFile>target/jacoco.exec</dataFile>
<outputDirectory>target/jacoco-ut</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,22 @@
package com.alibaba.testable.demo
class BlackBox(private val data: String) {
fun callMe(): String {
return data
}
fun trim(): String {
return data.trim()
}
fun substring(from: Int, to: Int): String {
return data.substring(from, to)
}
fun startsWith(prefix: String): Boolean {
return data.startsWith(prefix)
}
}

View File

@ -0,0 +1,11 @@
package com.alibaba.testable.demo
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication
@SpringBootApplication
class DemoApplication
fun main(args: Array<String>) {
runApplication<DemoApplication>(*args)
}

View File

@ -0,0 +1,61 @@
package com.alibaba.testable.demo
import org.springframework.stereotype.Service
import sun.net.www.http.HttpClient
import java.net.URL
@Service
class DemoService {
private var count = 0
/**
* Target 1 - private method
*/
private fun privateFunc(s: String, i: Int): String {
return "$s - $i"
}
/**
* Target 2 - method with private field access
*/
fun privateFieldAccessFunc(): String {
count += 2
return count.toString()
}
/**
* Target 3 - method with new operation
*/
fun newFunc(): String {
return BlackBox("something").callMe()
}
/**
* Target 4 - method with member method invoke
*/
fun outerFunc(s: String): String {
return "{ \"res\": \"" + innerFunc(s) + "\"}"
}
/**
* Target 5 - method with common method invoke
*/
fun commonFunc(): String {
val box = BlackBox("anything")
return box.trim() + "__" + box.substring(1, 2) + "__" + box.startsWith("any")
}
fun callerOne(): String {
return callFromDifferentMethod()
}
fun callerTwo(): String {
return callFromDifferentMethod()
}
private fun innerFunc(s: String) = HttpClient.New(URL("http:/xxx/$s")).urlFile
private fun callFromDifferentMethod() = "realOne"
}

View File

@ -0,0 +1 @@

View File

@ -0,0 +1,13 @@
package com.alibaba.testable.demo
import org.junit.jupiter.api.Test
import org.springframework.boot.test.context.SpringBootTest
@SpringBootTest
class DemoApplicationTests {
@Test
fun contextLoads() {
}
}

View File

@ -0,0 +1,81 @@
package com.alibaba.testable.demo
import com.alibaba.testable.core.accessor.PrivateAccessor
import com.alibaba.testable.core.annotation.EnableTestable
import com.alibaba.testable.core.annotation.TestableInject
import com.alibaba.testable.core.util.TestableUtil
import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.Test
import java.util.concurrent.Callable
@EnableTestable
internal class DemoServiceTest {
@TestableInject
private fun createBlackBox(text: String) = BlackBox("mock_$text")
@TestableInject
private fun innerFunc(text: String) = "mock_$text"
@TestableInject(targetClass = "com.alibaba.testable.demo.BlackBox")
private fun trim(self: BlackBox) = "trim_string"
@TestableInject(targetClass = "com.alibaba.testable.demo.BlackBox", targetMethod = "substring")
private fun sub(self: BlackBox, i: Int, j: Int) = "sub_string"
@TestableInject(targetClass = "com.alibaba.testable.demo.BlackBox")
private fun startsWith(self: BlackBox, s: String) = false
@TestableInject
private fun callFromDifferentMethod() = when (TestableUtil.currentSourceMethodName(this)) {
"callerOne" -> "mock_one"
else -> "mock_others"
}
private val demoService = DemoService()
@Test
fun should_able_to_test_private_method() {
Assertions.assertEquals("hello - 1", PrivateAccessor.invoke(demoService, "privateFunc", "hello", 1))
}
@Test
fun should_able_to_test_private_field() {
PrivateAccessor.set(demoService, "count", 3)
Assertions.assertEquals("5", demoService.privateFieldAccessFunc())
Assertions.assertEquals(5, PrivateAccessor.get(demoService, "count"))
}
@Test
fun should_able_to_test_new_object() {
Assertions.assertEquals("mock_something", demoService.newFunc())
}
@Test
fun should_able_to_test_member_method() {
Assertions.assertEquals("{ \"res\": \"mock_hello\"}", demoService.outerFunc("hello"))
}
@Test
fun should_able_to_test_common_method() {
Assertions.assertEquals("trim_string__sub_string__false", demoService.commonFunc())
}
@Test
fun should_able_to_get_source_method_name() {
Assertions.assertEquals("mock_one", demoService.callerOne())
Assertions.assertEquals("mock_others", demoService.callerTwo())
Assertions.assertEquals("mock_one_mock_others", Callable<String> {
demoService.callerOne() + "_" + demoService.callerTwo()
}.call())
}
@Test
fun should_able_to_get_test_case_name() {
Assertions.assertEquals("should_able_to_get_test_case_name", TestableUtil.currentTestCaseName(this))
Assertions.assertEquals("should_able_to_get_test_case_name", Callable<String> {
TestableUtil.currentTestCaseName(this)
}.call())
}
}

17
demo/pom.xml Executable file
View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.alibaba.testable</groupId>
<artifactId>demo</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>pom</packaging>
<name>demos</name>
<modules>
<module>java-demo</module>
<module>kotlin-demo</module>
</modules>
</project>

View File

@ -11,6 +11,7 @@
<modules>
<module>agent</module>
<module>core</module>
<module>demo</module>
</modules>
</project>