一起使用 JMockit 和 Spring AOP
Using JMockit and Spring AOP together
假设我有一个如下所示的程序:
@Component
public class MainAction {
public void doTheAction() {
System.out.println("Now doing the action");
}
}
@Aspect
@Component
public class BeforeAspect {
@Autowired
private Logger logger;
@Before("execution(* thepackagename.MainAction.*(..))")
public void doBefore() {
logger.log("The @Before advice has run");
}
}
@Component
public class Logger {
public void log(String s) {
System.out.println(s);
}
}
如果我通过 Eclipse 运行 它工作正常(主要方法在 Spring 创建 mainAction
之后调用 mainAction.doTheAction()
)。
现在我想编写一个测试,确保在调用 doTheAction
时正确调用 log
方法。我们正在使用 JMockit 进行测试。 (这是我实际面临的问题的一个非常简化的案例;通过 AOP 方面调用了一个更复杂的记录器,并且记录了错误的值。在进行修复之前,我正在尝试编写一个测试以确保记录的值正确。)
这是我的(简化的)测试目前的样子:
@RunWith(JMockit.class)
@ContextConfiguration(locations = {"classpath:Beans.xml"})
public class MainActionTest {
@Tested
private MainAction mainAction;
@Test
public void testThatLoggerIsCalled(@Injectable Logger logger) {
new Expectations() { {
logger.log(anyString);
} };
mainAction.doTheAction();
}
}
@ContextConfiguration
可能没用。早些时候我曾尝试过 @RunWith(SpringJunit4ClassRunner.class)
,这就是 @ContextConfiguration
在那里的原因,但是处理了 none 的模拟内容。另外,我按照 this question 中的建议使用 @Tested
和 @Injectable
而不是 @Autowired
和 @Mocked
;否则,mainAction
仍然为空。所以现在测试 运行s, and Now doing the action
出现在输出中。但是 The @Before advice has run
没有出现(即使我不嘲笑 Logger
也没有出现),期望失败了。
如何将 JMockit 和 AOP 结合使用?
编辑: 根据要求,我添加了一些内容来打印类路径 属性。这是(删除了一些路径名中不重要的部分):
Eclipse workspaces\springtest8\target\test-classes
Eclipse workspaces\springtest8\target\classes
C:\eclipse\plugins\org.junit_4.11.0.v201303080030\junit.jar
C:\eclipse\plugins\org.hamcrest.core_1.3.0.v201303031735.jar
.m2\repository\org\jmockit\jmockit.18\jmockit-1.18.jar
.m2\repository\junit\junit.11\junit-4.11.jar
.m2\repository\org\hamcrest\hamcrest-core.3\hamcrest-core-1.3.jar
.m2\repository\org\springframework\spring-context.2.0.RELEASE\spring-context-4.2.0.RELEASE.jar
.m2\repository\org\springframework\spring-aop.2.0.RELEASE\spring-aop-4.2.0.RELEASE.jar
.m2\repository\aopalliance\aopalliance.0\aopalliance-1.0.jar
.m2\repository\org\springframework\spring-beans.2.0.RELEASE\spring-beans-4.2.0.RELEASE.jar
.m2\repository\org\springframework\spring-core.2.0.RELEASE\spring-core-4.2.0.RELEASE.jar
.m2\repository\commons-logging\commons-logging.2\commons-logging-1.2.jar
.m2\repository\org\springframework\spring-expression.2.0.RELEASE\spring-expression-4.2.0.RELEASE.jar
.m2\repository\org\aspectj\aspectjrt.8.6\aspectjrt-1.8.6.jar
.m2\repository\org\aspectj\aspectjweaver.8.6\aspectjweaver-1.8.6.jar
.m2\repository\org\springframework\spring-test.2.0.RELEASE\spring-test-4.2.0.RELEASE.jar
.m2\repository\javax\inject\javax.inject\javax.inject-1.jar
/C:/eclipse/configuration/org.eclipse.osgi/bundles/201/1/.cp/
/C:/eclipse/configuration/org.eclipse.osgi/bundles/200/1/.cp/
编辑 2: 我通过从 Configure Build Path 的 Libraries 选项卡中删除 JUnit4 来让事情正常进行。
我从来不需要用 RunWith 注释 JUnit 测试来使用 JMockit。从 documentation 您需要确保在 junit 之前加载 jmockit jar 或添加 javaagent jvm 参数。这样您就可以 运行 使用 Spring 的 Junit Runner 进行测试,并将 JMockit 作为模拟框架。
以下测试工作正常,使用 Spring 3.0 或更新版本(使用 Spring 3.0.7、4.0.5 和 4.2.0 测试):
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:beans.xml")
public class MainActionTest
{
@Inject MainAction mainAction;
@Test
public void testThatLoggerIsCalled(@Mocked final Logger logger)
{
mainAction.doTheAction();
new Verifications() {{ logger.log(anyString); }};
}
}
假设我有一个如下所示的程序:
@Component
public class MainAction {
public void doTheAction() {
System.out.println("Now doing the action");
}
}
@Aspect
@Component
public class BeforeAspect {
@Autowired
private Logger logger;
@Before("execution(* thepackagename.MainAction.*(..))")
public void doBefore() {
logger.log("The @Before advice has run");
}
}
@Component
public class Logger {
public void log(String s) {
System.out.println(s);
}
}
如果我通过 Eclipse 运行 它工作正常(主要方法在 Spring 创建 mainAction
之后调用 mainAction.doTheAction()
)。
现在我想编写一个测试,确保在调用 doTheAction
时正确调用 log
方法。我们正在使用 JMockit 进行测试。 (这是我实际面临的问题的一个非常简化的案例;通过 AOP 方面调用了一个更复杂的记录器,并且记录了错误的值。在进行修复之前,我正在尝试编写一个测试以确保记录的值正确。)
这是我的(简化的)测试目前的样子:
@RunWith(JMockit.class)
@ContextConfiguration(locations = {"classpath:Beans.xml"})
public class MainActionTest {
@Tested
private MainAction mainAction;
@Test
public void testThatLoggerIsCalled(@Injectable Logger logger) {
new Expectations() { {
logger.log(anyString);
} };
mainAction.doTheAction();
}
}
@ContextConfiguration
可能没用。早些时候我曾尝试过 @RunWith(SpringJunit4ClassRunner.class)
,这就是 @ContextConfiguration
在那里的原因,但是处理了 none 的模拟内容。另外,我按照 this question 中的建议使用 @Tested
和 @Injectable
而不是 @Autowired
和 @Mocked
;否则,mainAction
仍然为空。所以现在测试 运行s, and Now doing the action
出现在输出中。但是 The @Before advice has run
没有出现(即使我不嘲笑 Logger
也没有出现),期望失败了。
如何将 JMockit 和 AOP 结合使用?
编辑: 根据要求,我添加了一些内容来打印类路径 属性。这是(删除了一些路径名中不重要的部分):
Eclipse workspaces\springtest8\target\test-classes
Eclipse workspaces\springtest8\target\classes
C:\eclipse\plugins\org.junit_4.11.0.v201303080030\junit.jar
C:\eclipse\plugins\org.hamcrest.core_1.3.0.v201303031735.jar
.m2\repository\org\jmockit\jmockit.18\jmockit-1.18.jar
.m2\repository\junit\junit.11\junit-4.11.jar
.m2\repository\org\hamcrest\hamcrest-core.3\hamcrest-core-1.3.jar
.m2\repository\org\springframework\spring-context.2.0.RELEASE\spring-context-4.2.0.RELEASE.jar
.m2\repository\org\springframework\spring-aop.2.0.RELEASE\spring-aop-4.2.0.RELEASE.jar
.m2\repository\aopalliance\aopalliance.0\aopalliance-1.0.jar
.m2\repository\org\springframework\spring-beans.2.0.RELEASE\spring-beans-4.2.0.RELEASE.jar
.m2\repository\org\springframework\spring-core.2.0.RELEASE\spring-core-4.2.0.RELEASE.jar
.m2\repository\commons-logging\commons-logging.2\commons-logging-1.2.jar
.m2\repository\org\springframework\spring-expression.2.0.RELEASE\spring-expression-4.2.0.RELEASE.jar
.m2\repository\org\aspectj\aspectjrt.8.6\aspectjrt-1.8.6.jar
.m2\repository\org\aspectj\aspectjweaver.8.6\aspectjweaver-1.8.6.jar
.m2\repository\org\springframework\spring-test.2.0.RELEASE\spring-test-4.2.0.RELEASE.jar
.m2\repository\javax\inject\javax.inject\javax.inject-1.jar
/C:/eclipse/configuration/org.eclipse.osgi/bundles/201/1/.cp/
/C:/eclipse/configuration/org.eclipse.osgi/bundles/200/1/.cp/
编辑 2: 我通过从 Configure Build Path 的 Libraries 选项卡中删除 JUnit4 来让事情正常进行。
我从来不需要用 RunWith 注释 JUnit 测试来使用 JMockit。从 documentation 您需要确保在 junit 之前加载 jmockit jar 或添加 javaagent jvm 参数。这样您就可以 运行 使用 Spring 的 Junit Runner 进行测试,并将 JMockit 作为模拟框架。
以下测试工作正常,使用 Spring 3.0 或更新版本(使用 Spring 3.0.7、4.0.5 和 4.2.0 测试):
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:beans.xml")
public class MainActionTest
{
@Inject MainAction mainAction;
@Test
public void testThatLoggerIsCalled(@Mocked final Logger logger)
{
mainAction.doTheAction();
new Verifications() {{ logger.log(anyString); }};
}
}