A library that provides the ability to mock your final classes on Android.
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.

README.md

DexOpener

CircleCI Release Javadoc
Android

A library that provides the ability to mock your final classes on Android.

Example

See the dexopener-example directory.

Usage

There are two ways to use this library.

Note: Starting at version 0.13.0, DexOpener automatically detects the BuildConfig class of the target application. Therefore, you no longer need to use DexOpener.Builder. It will be deleted in the next major version.

DexOpenerAndroidJUnitRunner

If you do not have your own test instrumentation runner, all you need to do is specify DexOpenerAndroidJUnitRunner as the default test instrumentation runner.

android {
    defaultConfig {
        minSdkVersion 16 // 16 or higher
        testInstrumentationRunner 'com.github.tmurakami.dexopener.DexOpenerAndroidJUnitRunner'
    }
}

You can extend this class to create your custom AndroidJUnitRunner.

public class YourAndroidJUnitRunner extends DexOpenerAndroidJUnitRunner { ... }

If you want to replace the android.app.Application instance for testing, extend this class and implement newApplication() method as shown in the Tips.

DexOpener

If you already have your own test instrumentation runner, you can use DexOpener instead of DexOpenerAndroidJUnitRunner.

public class YourAndroidJUnitRunner extends AndroidJUnitRunner {
    @Override
    public Application newApplication(ClassLoader cl, String className, Context context)
            throws InstantiationException, IllegalAccessException, ClassNotFoundException {
        DexOpener.install(this);
        return super.newApplication(cl, className, context);
    }
}

Note: If you are using a class literal to replace the android.app.Application instance, you will need to use a string literal instead. See the Tips.

And make sure your test instrumentation runner is specified in your build.gradle.

android {
    defaultConfig {
        minSdkVersion 16 // 16 or higher
        testInstrumentationRunner 'your.app.YourAndroidJUnitRunner'
    }
}

Tips

Replacing the Application instance for testing

To instantiate your custom android.app.Application object other than default application, pass a string literal of that class name as the second argument to super.newApplication() in your test instrumentation runner.

@Override
public Application newApplication(ClassLoader cl, String className, Context context)
        throws InstantiationException, IllegalAccessException, ClassNotFoundException {

    ...

    return super.newApplication(cl, "your.app.YourTestApplication", context);
}

Do not call Class#getName() to get your Application class name. The following code may cause a class inconsistency error.

// This code may cause a class inconsistency error.
return super.newApplication(cl, YourTestApplication.class.getName(), context);

Limitations

The final classes you can mock on instrumented unit tests are only those under the package indicated by the applicationId in the android.defaultConfig section of your build.gradle. For example, if it is foo.bar, you can mock only the final classes belonging in foo.bar.**, such as foo.bar.Baz and foo.bar.qux.Quux. Therefore, you cannot mock the final classes of both Android system classes and third-party libraries, and cannot mock the final classes not belonging in that package, even if they are yours.

Installation

First, add the JitPack repository to your build.gradle.

repositories {
    maven { url 'https://jitpack.io' }
}

And then, add this library as androidTestImplementation dependency.

dependencies {
    androidTestImplementation 'com.github.tmurakami:dexopener:1.0.4'
}

Note: If you are using Multidex, you need to specify your BuildConfig class in the primary DEX file, otherwise, you will get a NoClassDefFoundError.

Notice

This library contains the classes of the following libraries:

They have been minified with ProGuard and repackaged with Jar Jar Links. In addition, dexlib2 has been backported to Java 7 with Retrolambda.

License

Copyright 2016 Tsuyoshi Murakami

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.