[英]Mockito NullPointerException thrown instead of custom ExitException
I'm trying to test the functionality of my ApplicationRunner
class which currently depends on a simple CLI
class. 我正在尝试测试
ApplicationRunner
类的功能,该类当前依赖于简单的CLI
类。 Using mockito, i'm attempting to mock the CLI
and determine the conditions on which a custom ExitException
is thrown. 我正在尝试使用
ExitException
模拟CLI
并确定引发自定义ExitException
的条件。 (when the CLI
s help()
method is shown). (显示
CLI
的help()
方法时)。 My issue is that the test is throwing a NullPointerException
rather than an ExitException
when it his the parse
function. 我的问题是,测试在
parse
函数时会抛出NullPointerException
而不是ExitException
。
Test code: 测试代码:
public class ApplicationRunnerTest {
@Mock
private APUCLI cli;
private ApplicationRunner runner;
@Before
public void prepareDependencies(){
MockitoAnnotations.initMocks(this);
runner = new ApplicationRunner();
}
@Test(expected = ExitException.class)
public void verifyHelpOptionsRun() throws Exception{
String[] args = new String[]{};
runner.run(args);
when(cli.parse(args)).thenReturn(null);
verify(cli, times(1)).parse(args);
verify(cli, times(1)).help();
}
}
The cli class which is mocked: cli类被嘲笑:
@Component("Cli")
public class APUCLI implements CLI {
@Override
public ParsedArgs parse(String args[]) {
System.out.println("Parsing CLI");
return null;
}
@Override
public void help() throws ExitException{
System.out.println("something");
throw new ExitException(1);
}
}
The APU Runner code. APU运行程序代码。
@Component("Runner")
public class ApplicationRunner implements APURunner{
@Inject
@Named("Cli")
private CLI commandLineInterface;
@Override
public void run(String[] args) throws ExitException{
ParsedArgs parsedArgs = getParsedArgs(args);
if(parsedArgs == null){
callHelp();
}
System.out.println("Running");
}
private ParsedArgs getParsedArgs(String[] args){
return commandLineInterface.parse(args);
}
private void callHelp() throws ExitException{
commandLineInterface.help();
}
}
The error: 错误:
java.lang.Exception: Unexpected exception, expected<Systems.biology.laboratory.ExitException> but was<java.lang.NullPointerException>
at org.junit.internal.runners.statements.ExpectException.evaluate(ExpectException.java:28)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
Caused by: java.lang.NullPointerException
at Systems.biology.laboratory.runners.ApplicationRunner.getParsedArgs(ApplicationRunner.java:33)
at Systems.biology.laboratory.runners.ApplicationRunner.run(ApplicationRunner.java:23)
at Systems.biology.laboratory.runners.ApplicationRunnerTest.verifyHelpOptionsRun(ApplicationRunnerTest.java:32)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.internal.runners.statements.ExpectException.evaluate(ExpectException.java:19)
... 15 more
You have two issues (at least) : 您有两个问题(至少):
1) You mock a APUCLI
instance : 1)您模拟一个
APUCLI
实例:
@Mock
private APUCLI cli;
But you never set it to the ApplicationRununer
instance under test. 但是您永远不会将其设置为受测试的
ApplicationRununer
实例。 So the APUCLI
field defined in the ApplicationRununer
instance is null
. 因此,在
ApplicationRununer
实例中定义的APUCLI
字段为null
。
You could provide a constructor that allows to set the dependency. 您可以提供一个允许设置依赖项的构造函数。
So you could replace : 因此,您可以替换:
@Inject
@Named("Cli")
private CLI commandLineInterface;
by : 创建人:
private CLI commandLineInterface;
@Inject
public ApplicationRunner(CLI commandLineInterface){
this.commandLineInterface = commandLineInterface;
}
You could so create it in this way : 您可以这样创建它:
@Before
public void prepareDependencies(){
MockitoAnnotations.initMocks(this);
runner = new ApplicationRunner(cli);
}
About the @Named
qualifier, sorry I am not sure about the way to specify it in a autowired constructor with a javax Inject
annotation. 关于
@Named
限定词,很抱歉,我不确定在带有javax Inject
注释的自动装配构造函数中指定它的方式。
So I prefer put this point aside. 因此,我宁愿将这一点放在一边。
2) You set the mock behavior after executing the method to test. 2)在执行要测试的方法后,设置模拟行为。 It is too late.It should be done before if you want that it be considered during the execution of the method to test.
为时已晚,如果要在执行测试方法时考虑它,则应在完成之前进行。
@Test(expected = ExitException.class)
public void verifyHelpOptionsRun() throws Exception{
String[] args = new String[]{};
// mock record first
when(cli.parse(args)).thenReturn(null);
// execute the method to test
runner.run(args);
// do some checks (if required)
verify(cli, times(1)).parse(args);
verify(cli, times(1)).help();
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.