实际上,这将是一个更复杂的问题。我只想在测试中使用AspectJ。找到了使用if()连接点和一些静态布尔字段的建议。此外,首先我开始使用aspect作为我的基本测试方法的内部静态类。经过一些实验,我把它换成了自己的班级,但实际上并没有得到我想要的结果。所以,我只是创建了一些测试项目。Maven pom。xml:
<?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>org.example</groupId>
<artifactId>Testing</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<mockito.version>3.11.2</mockito.version>
<aspectj.version>1.9.7</aspectj.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.7.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-inline</artifactId>
<version>${mockito.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
<version>${mockito.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>${aspectj.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>${aspectj.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M5</version>
<dependencies>
<!-- https://mvnrepository.com/artifact/org.junit.platform/junit-platform-surefire-provider
-->
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-surefire-provider</artifactId>
<version>1.3.2</version>
</dependency>
</dependencies>
<!--<configuration>
<argLine>-javaagent:${user.home}/.m2/repository/org/aspectj/aspectjweaver/${aspectj.version}/aspectjweaver-${aspectj.version}.jar</argLine>
</configuration>-->
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>1.14.0</version>
<configuration>
<complianceLevel>${maven.compiler.source}</complianceLevel>
<source>${maven.compiler.source}</source>
<target>${maven.compiler.target}</target>
<showWeaveInfo>true</showWeaveInfo>
<verbose>true</verbose>
<Xlint>ignore</Xlint>
<encoding>${project.build.sourceEncoding}</encoding>
</configuration>
<executions>
<execution>
<goals>
<!-- use this goal to weave all your main classes -->
<goal>compile</goal>
<!-- use this goal to weave all your test classes -->
<goal>test-compile</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
类别:A:
package classes;
public class A {
private String a = "classes.A";
public String getA()
{
return a;
}
public String getFromB()
{
return new B().getB();
}
}
B:
package classes;
public class B {
private String b = "classes.B";
public String getB() {
return b;
}
}
测试类:
package aspectj;
import classes.A;
import classes.B;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
public class NewTest {
private static boolean useAspect = false;
public static boolean isUseAspect() {
return useAspect;
}
@BeforeEach
void init()
{
useAspect = true;
}
@Test
public void changeValue()
{
B b = new B();
System.out.println(b.getB());
}
@Test
public void changeValueInA()
{
A a = new A();
System.out.println(a.getFromB());
}
}
Aspect类
package aspectj;
import org.aspectj.lang.Aspects;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
@Aspect
public class AspectB {
@Pointcut("if()")
public static boolean useAspect()
{
return NewTest.isUseAspect();
}
@Pointcut("call(* classes.B.getB())")
public void callTestMethod() {}
@Around("callTestMethod()")
public String myAdvice(ProceedingJoinPoint point) throws Throwable {
return "You have been hacked!";
}
}
主要类别:
package classes;
public class TestOutputHere {
public static void main(String[] args) {
System.out.println(new A().getFromB());
}
}
运行测试和主要方法后我得到了结果:
第二个结果对我来说不合适...所以经过一些实验并删除AeyJ依赖项的测试范围,删除if()JointPoint(我们不能使用src中的测试类)并将Aspect类放在src中,我得到了结果:
欲望的结果也不要脚给我。我真的不想为所有项目使用方面。在那之后,我只是试图为maven surefire插件使用一些带有配置的Load-Time编织:
<configuration>
<argLine>
-javaagent:${user.home}/.m2/repository/org/aspectj/aspectjweaver/${aspectj.version}/aspectjweaver-${aspectj.version}.jar
</argLine>
</configuration>
我得到了我想要的结果:
那么,成千上万封信后的问题在哪里?)问题是:
我会非常感谢你的回答!
您的代码中有几个问题:
>
您在每次测试之前设置useAspect=true
,但在测试结束后永远不要重置为false
。这会将上下文泄漏到您希望方面不活动的其他测试中。您应该清理它。
方面有一个if()
切入点,这取决于测试类中的静态方法。在正常情况下,测试类在应用程序运行时不可用。静态字段及其访问器方法(如果有)应该在方面类本身中。
package aspectj;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
@Aspect
public class AspectB {
private static boolean useAspect = false;
public static void setUseAspect(boolean useAspect) {
AspectB.useAspect = useAspect;
}
@Pointcut("call(* classes.B.getB()) && if()")
public static boolean callTestMethod() {
return useAspect;
}
@Around("callTestMethod()")
public String myAdvice(ProceedingJoinPoint point) throws Throwable {
return "You have been hacked!";
}
}
package aspectj;
import classes.A;
import classes.B;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
public class NewTest {
@BeforeEach
void init() {
AspectB.setUseAspect(true);
}
@AfterEach
void cleanUp() {
AspectB.setUseAspect(false);
}
@Test
public void changeValue() {
B b = new B();
System.out.println(b.getB());
}
@Test
public void changeValueInA() {
A a = new A();
System.out.println(a.getFromB());
}
}
很可能,你的方面是在src/test/java
而不是src/main/java
中定义的,这解释了为什么它只被编译成测试类而不是应用程序类。但后者是您所期望的,如果从一个应用程序类到另一个应用程序类的方法调用应该被拦截。因此,您需要将方面移动到主源代码中,并使aspectjrt
具有编译范围,而不是测试范围。
但是在这种情况下,如果方面只影响测试,我建议不要使用编译时编织(CTW),因为这意味着应用程序在其类路径上始终需要AspectJ运行时(见上文),即使方面处于非活动状态。只有当至少有时在应用程序运行时该方面也处于活动状态时,CTW才有意义。即使如此,如果负载时间编织(LTW)可能不是更好的解决方案,例如,如果它是一个很少使用的调试方面,这也是有争议的。CTW是生产方面的理想选择。在这种情况下,很明显,使用Java代理的LTW是正确的方法。正如您所说,您甚至不需要丑陋的静态字段和切入点。
我只想写一个JUnit测试用例,测试下面的代码是否成功地将目录复制到新目录。 请建议,我如何编写一个JUnit测试或模拟来测试上面的代码。
问题内容: 有没有办法在单个Maven项目中编译多个Java源目录? 问题答案: 你可以使用build-helper添加新的源目录:
testng.xml TestNG将扫描所有类路径以寻找测试类(PackageUtils#findClassesInPackage)。 不需要的测试来自依赖项。 如何配置TestNG以只在maven项目测试目录中查找测试类(默认编译为)?
This is the name of the directory where compiled templates are located. By default this is "./templates_c", meaning that it will look for the compile directory in the same directory as the executing p
问题内容: 我正在尝试使AspectJ编织工作在一个简单的Maven项目中,并且不确定它出了什么问题:当我使用“ mvn exec:java”运行代码时,看不到预期的输出。 我确定代码可以正常工作,因为我在STS中尝试了相同的方法,在这里工作良好。我只是想让AspectJ在Maven项目中工作。 任何有关如何调试此类问题的提示将不胜感激。 外观文件与代码位于同一文件夹中: Java文件: 问题答案