android - junit4 opening a getResources().openRawResource using mockito runs nullpointer -


android studio 2.1. preview 4 

i creating junit4 unit test test opening file contained in raw directory.

however, everytime code runs can null pointer openrawresource.

this function trying test. works when running on actual device. not in unit test.

public string getnewsfeed(context mcontext) {     inputstream inputstream = mcontext.getresources().openrawresource(r.raw.news_list); // null pointer      writer writer = new stringwriter();     char[] buffer = new char[1024];      try {         inputstreamreader inputreader = new inputstreamreader(inputstream, "utf-8");         bufferedreader bufferreader = new bufferedreader(inputreader);         int n;         while ((n = bufferreader.read(buffer)) != -1) {             writer.write(buffer, 0, n);         }          inputstream.close();     }     catch (ioexception ioexception) {         return "";     }      return writer.tostring(); } 

this test case

@runwith(mockitojunitrunner.class) public class newslistpresentertest {      @mock     private context mcontext;     @mock     private newslistpresenter mnewslistpresenter;      @org.junit.before     public void setup() throws exception {         mockitoannotations.initmocks(this);         mnewslistpresenter = new newslistpresenter(mcontext);     }      @org.junit.test     public void testloadnewsfeed() throws exception {         assertnotnull(mnewslistpresenter.getnewsfeed(mcontext));     } } 

many suggestions,

you confusing 2 types of unit tests in android. not clear many people i'll explain here.

why works on device: because instrumented test. instrumented test? test runs on real device/emulator , test code in 'src/androidtest' folder.

why doesn't work local junit test: because local junit tests not instrumented tests. local junit tests run on computer's jvm, not on device. local junit tests shouldn't contain/use android code because real android code on device/emulator, not on computer's jvm.

i suppose want make run junit test run faster, , that's why suppose moved test 'src/test' folder , context.getresources() throwing nullpointerexception.

i think have 2 options here:

  1. use robolectric run test junit test
  2. refactor method doesn't depend on android's classes

for option 2, do. change method's argument inputstream:

public string getnewsfeed(inputstream inputstream) {... use inputstream... } 

now method doesn't see android code , can test normal junit method. pass fake inputstream method, this:

@test public void testloadnewsfeed() throws exception {     string filecontents = "line one";     inputstream inputstream = new bytearrayinputstream(filecontents.getbytes());     assertnotnull(mnewslistpresenter.getnewsfeed(inputstream)); } 

if still want pass same inputstream you're using in app (i wouldn't recommend it) still can using code in test:

@test     public void testloadnewsfeed() throws exception {         inputstream inputstream = this.getclass().getclassloader().getresourceasstream("raw/news_list");         assertnotnull(mnewslistpresenter.getnewsfeed(inputstream));     } 

and you'll have add line build.gradle file:

sourcesets.test.resources.srcdirs += ["src/main"] 

android unit tests can confusing. can read these concepts in this blog post wrote


Comments