问题
I have a class that I need to test with mockito. Below is the class and the Mockito Test.
dbBuilder.parse(file)
always returns null because it calls several classes which, in turn, call several methods in a jar file. Even though I mocked all of them it always returns null. I couldn't track where the null value is coming from. I tried to suppress the methods but still no use.
Since this method call returns null, the doc value is null. So the doc calls the getElementsByTagName
method and running the mockito tests fails with NullPointerException
. There are several lines of code after this code in this method i need to test.
How do I resolve this issue?
class DocumentClass{
public void docMethod(){
DocumentBuilder dbBuilder = new DocumentBuilder();
Document doc = new Document();
FileStream file = new FileStream(new File(some path));
doc = dbBuilder.parse(file);
NodeList nodes = doc.getElementsByTagName("documents");
}
}
@RunWith(PowerMockRunner.class)
@PrepareForTest({Document.class,DocumentBuilder.class,FileStream.class})
public class TestDocument{
@Test
public documentTest(){
DocumentBuilder dbBuilder = PowerMockito.mock(DocumentBuilder.class);
Document doc = PowerMockito.mock(Document.class);
FileStream file = PowerMockito.mock(FileStream.class);
PowerMockito.whenNew(FileStream.class).withAnyArguments().thenReturn(file);
PowerMockito.doReturn(doc).when(dbBuilder).parse(file);
DocumentClass docClass = PowerMockito.mock(DocumentClass.class);
docClass.docMethod();
}
}
回答1:
Edit: I realise you've mentioned that you've tried the whenNew before, but I'm providing the answer in a bit more detail so as to check all of the details required for this to work.
It looks to me like you'll need to mock the constructor call for the DocumentBuilder class. When you do this, you need to include the class that calls the constructor in the PrepareForTest annotation, so make sure that DocumentClass
exists there. See the documentation(primarily the quick summary) for what to prepare for test when mocking constructor calls.
Then, you'll also need to provide an expectation call for the method call on the DocumentBuilder.
Also, I don't think you need to call the constructor for the Document class, you're not doing anything with it before you simply replace the reference with the one from the dbBuilder.
So I think your method can look like this:
class DocumentClass{
public void docMethod(){
final FileStream file = new FileStream(new File(some path));
final DocumentBuilder dbBuilder = new DocumentBuilder();
final Document doc = dbBuilder.parse(file);
final NodeList nodes = doc.getElementsByTagName("documents");
}
}
So I think your test wants to look something like this: (I have not tried this code, so I apologise for any typos)
@RunWith(PowerMockRunner.class)
@PrepareForTest({DocumentClass.class, Document.class, DocumentBuilder.class, FileStream.class})
public class TestDocument {
@Test
public documentTest() {
final DocumentBuilder dbBuilder = PowerMockito.mock(DocumentBuilder.class);
final Document doc = PowerMockito.mock(Document.class);
final FileStream file = PowerMockito.mock(FileStream.class);
final NodeList nodes = PowerMockito.mock(NodeList.class);
PowerMockito.whenNew(FileStream.class).withAnyArguments().thenReturn(file);
PowerMockito.whenNew(DocumentBuilder).thenReturn(dbBuilder);
PowerMockito.doReturn(doc).when(dbBuilder).parse(file);
PowerMockito.doReturn(node).when(doc).getElementsByTagName("documents");
PowerMock.replayAll();
DocumentClass docClass = new DocumentClass();
docClass.docMethod();
PowerMock.verifyAll();
}
}
回答2:
You didn't use PowerMockito.whenNew(DocumentBuilder.class)
so the builder in use is a real builder, not a mock.
来源:https://stackoverflow.com/questions/25120820/mockito-mocked-object-is-assigned-a-null-value-from-method-calls-inside-a-method