我有一些处理器whitch执行一些任务。它有注释Component
。
@Component
public class Processor implements IProcessor {
@Autowired
private ConsumerTemplate consumerTemplate;
@Autowired
private IMessageService messageService;
@Override
public void process() {
Message message = consumerTemplate.receive("activemq:queue").getIn(); //line 37
String id = (String) message.getBody();
StatusEnum status = StatusEnum.valueOf((String) message.getHeader("status"));
if (status.equals(StatusEnum.CUSTOM)) {
String exceptionMessage = (String) message.getHeader("exception_message");
messageService.updateStatus(id, status, exceptionMessage);
} else {
messageService.updateStatus(id, status);
}
}
}
用于石英作业
public class ProcessingJob extends QuartzJobBean {
private IProcessor processor;
@Override
protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
processor.process();
}
public void setProcessor(IProcessor processor) {
this.processor = processor;
}
}
我想用
测试它public class ProcessingJobTest {
private ProcessingJob notificationProcessingJob;
private IProcessor processor;
private JobExecutionContext context;
@Before
public void setUp() {
processingJob = createMock(ProcessingJob.class);
processor = new Processor();
context = createMock(JobExecutionContext.class);
}
@Test
public void testExecuteInternal() throws JobExecutionException {
processor.process(); // line 40
expectLastCall();
replay(processingJob);
processingJob.executeInternal(context);
verify(processingJob);
}
}
但我有错误
java.lang.NullPointerException
at com.processor.Processor.process(Processor.java:37)
at com.scheduler.ProcessingJobTest.testExecuteInternal(ProcessingJobTest.java:40)
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:601)
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.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
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.junit.runners.ParentRunner.run(ParentRunner.java:309)
at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecuter.runTestClass(JUnitTestClassExecuter.java:80)
at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecuter.execute(JUnitTestClassExecuter.java:47)
at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassProcessor.processTestClass(JUnitTestClassProcessor.java:69)
at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.processTestClass(SuiteTestClassProcessor.java:49)
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:601)
at org.gradle.messaging.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35)
at org.gradle.messaging.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
at org.gradle.messaging.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:32)
at org.gradle.messaging.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:93)
at com.sun.proxy.$Proxy2.processTestClass(Unknown Source)
at org.gradle.api.internal.tasks.testing.worker.TestWorker.processTestClass(TestWorker.java:103)
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:601)
at org.gradle.messaging.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35)
at org.gradle.messaging.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
at org.gradle.messaging.remote.internal.hub.MessageHub$Handler.run(MessageHub.java:355)
at org.gradle.internal.concurrent.DefaultExecutorFactory$StoppableExecutorImpl$1.run(DefaultExecutorFactory.java:66)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:722)
为什么呢?问题是什么?
答案 0 :(得分:1)
字段ConsumerTemplate consumerTemplate
未初始化,因此null
因此是NPE。
Spring DI在单元测试中默认不起作用,JUnit对@Autowired
和@Component
一无所知。如果你真的想走这条路,你应该看一下集成测试章节:http://docs.spring.io/spring/docs/current/spring-framework-reference/html/testing.html#integration-testing
我个人更喜欢将您的实现更改为构造函数注入,这会使测试SUT更容易(并且非常清楚为什么您的测试失败):
@Component
public class Processor implements IProcessor {
private ConsumerTemplate consumerTemplate;
private IMessageService messageService;
@Autowired
public Processor(ConsumerTemplate consumerTemplate, IMessageService messageService){
this.consumerTemplate = consumerTemplate;
this.messageService = messageService;
}
...
}
引用Oliver Gierkes post
Field injections is evil… hides dependencies, instead of making them explicit