31

I'm trying to create a test fixture using Fitnesse framework, and I want to test a function which retrieves data from a server (RESTFUL service). My test case is very simple:

public class FriendListActivityFixture extends ColumnFixture {
    public int URL;
    public String test() {
    JSONArray array = JsonHelper.getJsonArrayFromUrl("http://107.22.209.62/android/get_users.php");
    return array.toString();
    }
}

public static JSONArray getJsonArrayFromUrl(String url) {
        InputStream input = null;
        String result = "";
        JSONArray jsonArray = null;
        try {
            HttpClient httpclient = CustomHttpClient.getHttpClient();
            HttpPost httppost = new HttpPost(url);
            HttpResponse response = httpclient.execute(httppost);
            HttpEntity entity = response.getEntity();
            input = entity.getContent();
        }
        catch (Exception e) {
            Log.e(TAG + ".getJsonArrayFromUrl(String url)", "Error in http connection " + e.toString()); 
        }

        try {
            BufferedReader reader = new BufferedReader(new InputStreamReader(input, "iso-8859-1"), 8);
            StringBuilder content = new StringBuilder();
            String line = null;
            while ((line = reader.readLine()) != null) {
                content.append(line + "\n");
            }
            input.close();
            result = content.toString();
        }
        catch (Exception e) {
            Log.e(TAG + ".getJsonArrayFromUrl(String url)", "Error parsing result " + e.toString());
        }

        try {
            jsonArray = new JSONArray(result);
        }
        catch (JSONException e) {
            Log.e(TAG + "getJsonArrayFromUrl(String url)", "Error converting data " + e.toString());
        }
        return jsonArray;
    }

And here is the Fitnesse test page:!path fitnesse.jar

!path C:\Program Files (x86)\Android\android-sdk\platforms\android-10\android.jar
!path C:\Users\chan\git\Spotr\Spotr\bin\classes

!|com.csun.spotr.fitnesse.FriendListActivityFixture|
|URL|test?|
|0|"wwa"|

Since it's just a demo, my test might look a bit silly at the moment. Unfortunately, I keep getting these errors:

java.lang.RuntimeException: Stub!
    at android.util.Log.e(Log.java:15)
    at com.csun.spotr.util.JsonHelper.getJsonArrayFromUrl(JsonHelper.java:75)
    at com.csun.spotr.fitnesse.FriendListActivityFixture.test(FriendListActivityFixture.java:30)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at fit.TypeAdapter.invoke(TypeAdapter.java:109)
    at fit.TypeAdapter.get(TypeAdapter.java:97)
    at fit.Fixture$CellComparator.compareCellToResult(Fixture.java:371)
    at fit.Fixture$CellComparator.access$100(Fixture.java:357)
    at fit.Fixture.compareCellToResult(Fixture.java:299)
    at fit.Fixture.check(Fixture.java:295)
    at fit.ColumnFixture.check(ColumnFixture.java:51)
    at fit.Binding$QueryBinding.doCell(Binding.java:215)
    at fit.ColumnFixture.doCell(ColumnFixture.java:37)
    at fit.Fixture.doCells(Fixture.java:171)
    at fit.Fixture.doRow(Fixture.java:165)
    at fit.ColumnFixture.doRow(ColumnFixture.java:25)
    at fit.Fixture.doRows(Fixture.java:159)
    at fit.ColumnFixture.doRows(ColumnFixture.java:18)
    at fit.Fixture.doTable(Fixture.java:153)
    at fit.Fixture.interpretTables(Fixture.java:99)
    at fit.Fixture.doTables(Fixture.java:79)
    at fit.FitServer.process(FitServer.java:81)
    at fit.FitServer.run(FitServer.java:56)
    at fit.FitServer.main(FitServer.java:41)

And I have no idea what is it telling me? I wrote other testing method like add(), substract(), everything worked fine. I wonder does this error involve running a long task on the main thread? Any idea?

roxrook
  • 13,511
  • 40
  • 107
  • 156

4 Answers4

52

android.jar contains only stub implementation of the classes. It provides the means for you app to build, once you have your APK you must run it on an android device or emulator.

If I'm not wrong you are trying to run on host's JVM.

Diego Torres Milano
  • 65,697
  • 9
  • 111
  • 134
  • Thanks, my test fixture class doesn't contain any Activity code though, so I don't understand why I have to run it on the device. Anyway, let me try it run it on the device. – roxrook Jan 24 '12 at 07:19
  • 1
    Did you mean you want to see my `Log`? – roxrook Jan 25 '12 at 15:23
  • I'm seeing your log and that's what first line says – Diego Torres Milano Jan 25 '12 at 18:06
  • Hi, I'm using EclEmma to get coverage from a test, and seem to be getting that issue as well. The impression I get from your answer is that this occurs because EclEmma isn't running with the emulator. Do you know of a way to get this to work? – NioShobu Aug 22 '12 at 23:02
  • I removed the jar cleaned the project and added it again and it worked! – raghul Dec 18 '12 at 11:44
  • I first encountered this issue when using `Log` as well. I would call this (specifically the fact that `Log` throws an RTE) a rather severe violation of the principle of least surprise. – jordanpg Oct 06 '14 at 22:45
11

You can fix this problem and test within your IDE really easily by using Roboelectric.

As dtmilano said, you can't run Android code on your laptop as is, but Roboelectric basically substitutes the actual method implementations for the stubs in Android.jar.

Two things to watch out for if you go with this solution:

  • Make sure that your JAR import is above the Android JAR in your dependencies list if using IntelliJ

  • It defaults to blocking HTTP requests under the assumption that you don't actually want to change the state of a server somewhere. You can, however, disable this quite easily: Roboelectric.getFakeHttpLayer().interceptHttpRequests(false);

Alex
  • 18,332
  • 10
  • 49
  • 53
5

As mentioned previously, Android jars are not good for anything beyond compiling. Even most innocent things are stubbed out completely. But you can still use them in host VM unit tests with good mocking frameworks. My choice is jmockit:

Not sure whether it will work with Fitnesse though

Jacob
  • 34,255
  • 14
  • 110
  • 165
Konstantin Pribluda
  • 12,329
  • 1
  • 30
  • 35
  • 1
    Many thanks for the example. However I still think Fitnesse is a better way to write test, since it's easier to document along the way. – roxrook Jan 24 '12 at 07:22
  • 1
    ... but test functionality is still important. And it may be as well compatiblewith mocking frameworks – Konstantin Pribluda Jan 24 '12 at 10:12
1

I had this same issue because of the "static" declaration. In my case, .build() caused the issue in a static variable. The simple solution was to not declare the variable static. It can be final. Try removing "static" from the getJsonArrayFromUrl method and see if it works.

Janin
  • 292
  • 1
  • 2
  • 7