android - Unit Testing ActiveAndroid Models Using Robolectric -
i using activeandroid of models, , wanted start unit testing work. unfortunately, getting load of errors, namely in being unable initialize activeandroid using proper context.
activeandroid iniatilized:
activeandroid.initialize(context)
i have tried initialize context by:
have stub class extends application, , use initialize db.
private class testapp extends com.activeandroid.app.application{ @override public void oncreate() { super.oncreate(); initialisedb(getdatabasename()); } protected string getdatabasename() { return "sad"; } private void initialisedb(string dbname) { activeandroid.initialize(this); } }
this fails, class return null .getpackagename() , .getapplicationcontext(), both of used internally initialize.
i have tried using shadowcontextwrapper, may using wrong. here how went it:
shadowcontextwrapper shadowcontextwrapper = new shadowcontextwrapper(); shadowcontextwrapper.setapplicationname("appname"); shadowcontextwrapper.setpackagename("package"); context context = shadowcontextwrapper.getapplicationcontext();
this approach fails npe @ shadowcontextwrapper.java:52 part of robolectric. line itself:
context applicationcontext = this.realcontextwrapper.getbasecontext().getapplicationcontext();
i using 1.2, robolectric3.0 , activeandroid 3.1.
here example of test running.
@runwith(customrobolectrictestrunner.class) public class itemtest { public void setup(){ } @test public void checkjunitwork() { assertthat(true, is(true)); } @test public void testsave(){ item item = new item("name", "units", 5.0, 4.5, 10.0); assertthat(item.getname(),is("name")); } public void teardown(){ } }
my custom runner follows:
public class customrobolectrictestrunner extends robolectrictestrunner { public customrobolectrictestrunner(class<?> testclass) throws initializationerror { super(testclass); string buildvariant = (buildconfig.flavor.isempty() ? "" : buildconfig.flavor+ "/") + buildconfig.build_type; string intermediatespath = buildconfig.class.getresource("") .tostring().replace("file:", ""); intermediatespath = intermediatespath .substring(0, intermediatespath.indexof("/classes")); system.setproperty("android.package", buildconfig.application_id); system.setproperty("android.manifest", intermediatespath + "/manifests/full/" + buildvariant + "/androidmanifest.xml"); system.setproperty("android.resources", intermediatespath + "/res/" + buildvariant); system.setproperty("android.assets", intermediatespath + "/assets/" + buildvariant); shadowcontextwrapper shadowcontextwrapper = new shadowcontextwrapper(); shadowcontextwrapper.setapplicationname("appname"); shadowcontextwrapper.setpackagename("package"); context context = shadowcontextwrapper.getapplicationcontext(); activeandroid.initialize(context); }
}
so, issue you're having tests testapp
not running. running, need setup test use manifest specifies testapp
application run.
setup testapp follows somewhere in /test
directory of source tree... e.g. /src/test/java/some-long-package/testapp.java
:
package com.some.company; public class testapp extends application { @override public void oncreate() { super.oncreate(); activeandroid.initialize(this); } }
this important part
create android manifest file in /test
tree of source. have manifest file specify testapp
application. so, create manifest @ path /src/test/resources/testmanifest.xml
containing following:
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.android.test"> <application android:name="com.some.company.testapp"> </application> </manifest>
i'd recommend getting rid of customrobolectrictestrunner
default robolectric 3.0 test runner of need done. if need test various build variants, use @runwith(robolectricgradletestrunner.class)
.
but now, setup tests follows:
@runwith(robolectrictestrunner.class) @config(constants = buildconfig.class, manifest = "src/test/resources/testmanifest.xml", sdk = build.version_codes.lollipop) public class mainapptest { @test public void runtimeapplicationshouldbetestapp() throws exception { string actualname = runtimeenvironment.application.getclass().getname(); string expectedname = testapp.class.getname(); assert(actualname).equals(expectedname); } }
that @config(manifest= ...)
bit setup robolectric use test manifest , test application. test above simple validates application context being used within test indeed testapp.class
ensure activeandroid initialized correctly test.
i agree eugen may trying little bit in tests. testing db through application, creating integration test. i'd recommend splitting out functionality as possible.
happy testing!