我目前正在爲使用Spring和AspectJ的應用程序中的類編寫JUnit單元測試。被測試的類有一些公共方法,這些方法在方面類中通過around-advice方法建議。 Aspect有兩個被注入的字段,即使我已經在測試應用程序上下文中成功實例化了這些bean,並且在調用它們的方法時,它們會拋出nullpointerexceptions,但在執行建議的方法時會變爲null。下面的代碼的簡化版本:單元測試@Around建議的方法
類來進行測試:
public class ClassUnderTest {
@Inject
private Foo foo;
@Audit(StringValue="arg", booleanValue=true)
public Object advisedMethod() {
Object ret = new Object();
//things happen
return ret;
}
的看點:
@Aspect
@Configurable
public class AuditAspect implements Versionable {
@Inject
Foo foo;
@Inject
Bar bar;
@Around("@annotation(Audit)")
public Object aroundAdvice(ProceedingJoinPoint pjp, Audit audit) {
// Things happen
privMethod(arg);
// Yet other things happen
Object ret = pjp.proceed();
// Still more things happen
return ret;
}
private Object privMethod(Object arg) {
// Things continue to happen.
// Then this throws a NullPointerException because bar is null.
bar.publicBarMethod(arg2);
// Method continues ...
}
}
審計接口:
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Audit {
String value() default "";
boolean bool() default false;
}
的配置文件提供應用上下文:
import static org.mockito.Mockito.*;
@Configuration
public class ClassUnderTestTestConfig {
@Bean
Foo foo() {
return mock(Foo.class);
}
@Bean
Bar bar() {
return mock(Bar.class);
}
@Bean
ClassUnderTest classUnderTest() {
return new ClassUnderTest();
}
@Bean
@DependsOn({"foo", "bar"})
Aspect aspect() {
return new Aspect();
}
}
測試類:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextHierarchy({
@ContextConfiguration(classes = ClassUnderTestTestConfiguration.class),
@ContextConfiguration(classes = ClassUnderTest.class)
})
public class ClassUnderTestTest {
private static final String sessionNumber = "123456";
@Inject
Foo foo;
@Inject
Bar bar;
@Inject
ClassUnderTest classUnderTest;
@Inject
Aspect aspect;
@Test
public void test() {
// This call triggers the advice which ends up throwning
// a NullPointerException.
classUnderTest.advised();
}
}
我也試着做我自己的春天代理,然後通過將此代碼添加到測試類手動添加方面它建議在this stack overflow post,:
@Before
public void setUp() {
DataPointRestWebService target = new DataPointRestWebService();
AspectJProxyFactory proxyMaker = new AspectJProxyFactory(target);
proxyMaker.addAspect(auditAspect);
dataPointRestWebService = proxyMaker.getProxy();
}
不過是結束了投擲:
AopConfigException: Advice must be declared inside an aspect type. Offending method 'public java.lang.Object Aspect.aroundAdvice' in class [Aspect]
我鰭d這個神祕的東西,因爲我的Aspect類在它之前確實有@Aspect註解,並且類在測試環境之外工作。
我對Spring和AspectJ非常陌生,所以我完全接受我對這一切都錯誤的看法。我在這裏提供了虛擬代碼,希望能夠省略無用的細節,但也因爲工作代碼是專有的,而不是我的。如果您認爲我遺漏了一個重要細節,請告訴我,我會嘗試添加它。
在此先感謝您的任何幫助,請讓我知道我是否遺漏了任何重要信息。
編輯:
根據要求,我已經添加了全NullPointerException異常堆棧跟蹤:
java.lang.NullPointerException
at com.unifiedcontrol.aspect.AuditAspect.getCaller(AuditAspect.java:265)
at com.unifiedcontrol.aspect.AuditAspect.ajc$inlineAccessMethod$com_unifiedcontrol_aspect_AuditAspect$com_unifiedcontrol_aspect_AuditAspect$getCaller(AuditAspect.java:1)
at com.unifiedcontrol.aspect.AuditAspect.aroundAuditAdvice(AuditAspect.java:79)
at com.unifiedcontrol.server.rest.DataPointRestWebServiceTest.dummyTest(DataPointRestWebServiceTest.java:109)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:74)
at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:83)
at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:72)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:233)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:87)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:71)
at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:176)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
凡AuditAspect ==看點和DataPointRestWebService == ClassUnderTest。
你的例子對我來說很好(沒有'@ Before'方法)。你能發佈完整的NPE堆棧跟蹤嗎? –
剛添加它。感謝您抽出寶貴的時間。 –
看起來你在'AuditAspect'中忽略了一些重要的東西。你能提供一個完整的和可重複的例子,即。一個[MCVE](http://stackoverflow.com/help/mcve)? –