spring-mvc - aop 方面作为春季测试中的模拟
问题描述
我偶然发现了一篇有趣的文章:AOP Aspects as mocks in JUnit
由于我需要模拟多个最终和私有静态变量,因此我计划使用 AOP 代替反射或 PowerMockito,因为它们会导致SpringJUnit4ClassRunner
.
有什么方法可以@Aspect
在不使用注释的情况下用于测试类@EnableAspectJAutoProxy
?(我只想在一个测试用例中使用面向类 X 的方面。)
这是我想做的一个示例。
问题得到了回答(添加讨论可以做什么)
//External class
public final class ABC(){
public void method1() throws Exception {}
}
@Service
public void DestClass() {
private static final ABC abc = new ABC();
public Object m() {
// code (...)
try {
abc.method1();
}
catch(Exception e) {
// do something (...)
return null;
}
// more code (...)
}
}
解决方案
Spring 框架允许以编程方式创建建议目标对象的代理,而无需通过@EnableAspectJAutoProxy
或配置<aop:aspectj-autoproxy>
可以在文档部分找到详细信息:@AspectJ Proxies 的编程创建,实现非常简单。
文档中的示例代码。
// create a factory that can generate a proxy for the given target object
AspectJProxyFactory factory = new AspectJProxyFactory(targetObject);
// add an aspect, the class must be an @AspectJ aspect
// you can call this as many times as you need with different aspects
factory.addAspect(SecurityManager.class);
// you can also add existing aspect instances, the type of the object supplied must be an @AspectJ aspect
factory.addAspect(usageTracker);
// now get the proxy object...
MyInterfaceType proxy = factory.getProxy();
请注意,使用 Spring AOP,只能建议方法执行。文档摘录
Spring AOP 当前仅支持方法执行连接点(建议在 Spring bean 上执行方法)。没有实现字段拦截,尽管可以在不破坏核心 Spring AOP API 的情况下添加对字段拦截的支持。如果您需要建议字段访问和更新连接点,请考虑使用 AspectJ 等语言。
与问题共享的文档是关于 aspectj 的,如果不提供要建议的示例代码,很难断定要求是否可以通过 Spring AOP 实现。该文件也提到了这一点。
AspectJ 集成的一个例子是 Spring 框架,它现在可以在其自己的 AOP 实现中使用 AspectJ 切入点语言。Spring 的实现并非专门针对测试解决方案。
希望这可以帮助。
--- 更新:一个不使用 AOP 的测试用例 ---
考虑外部类
public class ABCImpl implements ABC{
@Override
public void method1(String example) {
System.out.println("ABC method 1 called :"+example);
}
}
和DestClass
@Service
public class DestClass {
private static final ABC service = new ABCImpl();
protected ABC abc() throws Exception{
System.out.println("DestClass.abc() called");
return service;
}
public Object m() {
Object obj = new Object();
try {
abc().method1("test");
} catch (Exception e) {
System.out.println("Exception : "+ e.getMessage());
return null;
}
return obj;
}
}
以下测试类使用重写的逻辑自动装配DestClass
bean 以引发异常。可以修改此代码以适应您的要求。
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = { DestClassSpringTest.TestConfiguration.class })
public class DestClassSpringTest {
@Configuration
static class TestConfiguration {
@Bean
public DestClass destClass() {
return new DestClass() {
protected ABC abc() throws Exception {
// super.abc(); // not required . added to demo the parent method call
throw new Exception("Custom exception thrown");
}
};
}
}
@Autowired
DestClass cut;
@Test
public void test() {
Object obj = cut.m();
assertNull(obj);
}
}
以下将是输出日志
DestClass.abc() called // this will not happen if the parent method call is commented in DestClassSpringTest.TestConfiguration
Exception : Custom exception thrown
推荐阅读
- java - Spring Beans 实现接口的工厂
- java - Spring调度程序根据一天中的时间固定延迟
- audio - 自定义 HLS 段 - 调整 m3u8 - 可能吗?
- apache-spark - 使用缓存扩展堆内存
- java - 如何使用弹簧批处理集成从远程服务器(主服务器)在工作服务器的多个节点上运行/执行作业?
- python-3.x - 跟踪运行 Python Django 的函数的进度
- c - 我试图弄清楚这是否会以某种方式溢出
- fullcalendar - 全日历时间轴保持滚动位置
- ravendb - RavenDb:声明类型的强制序列化不是分配给集合的继承类型
- mysql - MySQL 更新返回成功但更新没有发生