Android Bundle simple unit test not working

2020-07-10 05:40发布

I'm quite new to android and trying to understand how bundle works.

I get blocked by the following unit test. Can someone please explain why it fails ?

@Test
public void testBundle() throws Exception {
    Bundle bundle = new Bundle();
    String key = "hello";
    String value = "world";
    bundle.putString(key, value);
    Assert.assertEquals(value, bundle.getString(key));
}

junit.framework.ComparisonFailure: 
Expected :world
Actual   :null

标签: android
2条回答
啃猪蹄的小仙女
2楼-- · 2020-07-10 06:11

JUnit tests run on a local machine which doesn't have all the Android source code present, but just stub classes (described here). These stub classes allow you to compile your Android app against them (because their API is identical to the actual Android framework), but they do not contain any logic in order to make them "light".

By default, if you attempt to invoke any of the stub methods you get an exception. Something like this:

public Bundle() {
    throw new RuntimeException("Stub!");
}

this "fail fast" approach was employed in order to prevent developers from accidentally running their code against these stub classes and then wondering why it doesn't work.

However, this behavior can be changed with this configuration in build.gradle:

android {
  ...
  testOptions {
    unitTests.returnDefaultValues = true
  }
}

this makes the stub methods return default value instead of throwing exceptions.

You probably have this feature enabled, therefore when you run your JUnit tests you don't get exception, but Bundle#getString() method just returns default value (which is null).

If you want to test code that has Android framework dependencies, you should do either of:

  1. Mock these dependencies (e.g. Mockito)
  2. Run tests with Robolectric
  3. Run instrumentation tests on Android device

In any case, unitTests.returnDefaultValues = true is a VERY DANGEROUS feature to use, because it makes your tests non-reliable: some test can pass because a default value was returned by stub method, but the functionality will fail on a real device. Turn it off.

查看更多
【Aperson】
3楼-- · 2020-07-10 06:31

As described in Building Local Unit Tests,

By default, the Android Plug-in for Gradle executes your local unit tests against a modified version of the android.jar library, which does not contain any actual code.

Your test code runs against a stripped version of Bundle which doesn't contain the actual implementation, hence you get null whenever you try to get something from it. If you actually want to test the behavior of a Bundle, I'd suggest writing an instrumentation test which runs on an Android device against the real Bundle implementation.

查看更多
登录 后发表回答