I'm trying to test the functionality of my ApplicationRunner
class which currently depends on a simple CLI
class. Using mockito, i'm attempting to mock the CLI
and determine the conditions on which a custom ExitException
is thrown. (when the CLI
s help()
method is shown). My issue is that the test is throwing a NullPointerException
rather than an ExitException
when it his the parse
function.
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:
@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.
@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 :
@Mock
private APUCLI cli;
But you never set it to the ApplicationRununer
instance under test. So the APUCLI
field defined in the ApplicationRununer
instance is 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.
So I prefer put this point aside.
2) You set the mock behavior after executing the method to test. 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();
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.