1

As i just started Mockito, I have below method that i want to test. In my YouTubeChannelImporter.java file there are both methods : readJsonFromUrl(String url) and readAll(rd)

public JSONObject readJsonFromUrl(String url) throws IOException,
            JSONException {
        InputStream is = new URL(url).openStream();
        try {
            BufferedReader rd = new BufferedReader(new InputStreamReader(is,
                    Charset.forName("UTF-8")));
            String jsonText = readAll(rd);
            JSONObject json = new JSONObject(jsonText);
            return json;
        } finally {
            is.close();
        }
    }

I started with some rough idea.Below is the sample test case.

 @Test
    public void readJsonFromUrl() throws IOException, JSONException {
       String urlTest="http://google.com/api";
       YouTubeChannelImporter mockYoutube = mock(YouTubeChannelImporter.class);
       YouTubeChannelImporter tubeChannelImporter =new YouTubeChannelImporter();
     //  URL url=new URL(urlTest);
     //  InputStream inputStream = mock(InputStream.class);
    //   when(url.openStream()).thenReturn(inputStream);
       BufferedReader rd=mock(BufferedReader.class);
       when(mockYoutube.readAll(rd)).thenReturn("{\"kind\":\"you\"}");
       String jsonText="{\"kind\":\"you\"}";
       JSONObject object=new JSONObject(jsonText);
       assertEquals("{\"kind\":\"you\"}",tubeChannelImporter.readJsonFromUrl(urlTest).toString());
    }

My issue is when i will test the function readJsonFromUrl(String url) then readAll(rd) should not execute. Rather mock should be in action here. I am aware this issue is because tubeChannelImporter.readJsonFromUrl(urlTest).toString() . Looking for any other way to achieve my goal. Thanks

Vivek Dhiman
  • 1,967
  • 6
  • 46
  • 82

2 Answers2

0

You're mocking one instance of your class, and then executing another - as you noticed, this does not achieve the intended result.

I think the easiest way of testing your method is with spying ("partial mocking"). With this technique, you'll have an actual instance of your class with only a single method, readAll mocked out:

@Test
public void readJsonFromUrl() throws IOException, JSONException {
   // Set up the spied instance:
   YouTubeChannelImporter tubeChannelImporter = spy(new YouTubeChannelImporter());
   doReturn("{\"kind\":\"you\"}").when(tubeChannelImporter).readAll(any(Reader.class));

   // Test the execution
   String urlTest="http://google.com/api";
   String jsonText="{\"kind\":\"you\"}";
   JSONObject object=new JSONObject(jsonText);
   assertEquals("{\"kind\":\"you\"}",tubeChannelImporter.readJsonFromUrl(urlTest).toString());
}
Mureinik
  • 297,002
  • 52
  • 306
  • 350
  • Hi I am getting NPE at when(tubeChannelImporter.readAll(any(Reader.class))).thenReturn("{\"kind\":\"you\"}"); . Also readAll accept Reader as argument where its defined. – Vivek Dhiman Jul 24 '14 at 09:43
  • @user3645799 copy-paste bug :-( Should have been done with `doReturn` since it's a spied object, not a mock - see my edit. – Mureinik Jul 24 '14 at 11:11
0

Personally, for a test like this where you have to read a file and there's not much else going on, I would read an actual file rather than mock out a BufferedReader. Then you just have to Assert on the JSONObject output from the call to readJsonFromUrl().

Your problems stem from trying to test against the private method readAll(). Try to test only your public methods in your tests (e.g. readJsonFromUrl()) and you'll find you have to jump through less hoops in your test code.

If your class already implements an Interface, then just write tests against the Interface.

If you find that you have a lot of private methods, perhaps your class is responsible for doing too much work, so factor methods out into their own class(es). Then you can test them in isolation.

If you have a maven project, the place to put your test files, to read from, is in /src/test/resources

Community
  • 1
  • 1
Brad
  • 15,186
  • 11
  • 60
  • 74