Firebase unit testing without involving a context - java

I am trying to unit test firebase code with JUnit 4 in Android Studio.
The following are the minimal unit test code and configs.
public class ATest {
private static Firebase f;
#BeforeClass
public static void init() {
f = new Firebase(FIREBASE_URL);
}
#Test
public void doTest(){}
}
build.gradle dependency
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
testCompile 'junit:junit:4.12'
compile 'com.firebase:firebase-client-jvm:2.5.0'
}
However, when running unit testing, exception occur at the line inside init().
java.lang.RuntimeException: You need to set the Android context using Firebase.setAndroidContext() before using Firebase.
at com.firebase.client.core.Context.getPlatform(Context.java:45)
at com.firebase.client.core.Context.ensureLogger(Context.java:218)
at com.firebase.client.core.Context.initServices(Context.java:105)
at com.firebase.client.core.Context.freeze(Context.java:92)
at com.firebase.client.core.RepoManager.getLocalRepo(RepoManager.java:55)
at com.firebase.client.core.RepoManager.getRepo(RepoManager.java:19)
at com.firebase.client.Firebase.<init>(Firebase.java:172)
at com.firebase.client.Firebase.<init>(Firebase.java:177)
at com.firebase.client.Firebase.<init>(Firebase.java:155)
at mypackage.Test.init(Test.java:21)
I did a test with eclipse/maven, including firebase-client-jvm doesn't result in RuntimeException. What configuration am I missing to cause the jvm version of Firebase to require a Context?

Related

Spock test case doesn't work without JUnit's #Test annotation

I have started new java 11, spring boot 2.3.1 project in IntelliJ.
I wanted to add spock to dependencies however I am facing a problem when trying to run example test case.
org.junit.runners.model.InvalidTestClassError: Invalid test class 'com.example.SpockSpec':
1. No runnable methods
This is list of my dependencies:
dependencies {
implementation 'org.springframework.boot:spring-boot-starter'
testImplementation('org.springframework.boot:spring-boot-starter-test') {
exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
}
testImplementation "org.codehaus.groovy:groovy-all:$groovyVersion"
testImplementation 'org.spockframework:spock-core:2.0-M2-groovy-3.0'
}
(groovy version is 3.0.0)
this is the spec:
class SpockSpec extends Specification {
def "result should be true"(){
given:
boolean a = false;
boolean b = true;
when:
boolean result = a || b;
then:
result == true;
}
}
Workaround is to add JUnit's #Test annotation before the method but I would prefer not to do that.
Also - when I do so testing only works when I run whole class.
How can I resolve the error?
Spock 1 is based on JUnit 4, but Spock 2 runs on the JUnit 5 platform, implementing its own engine (not JUnit Jupiter). So maybe you want to first read some documentation and then upgrade to JUnit 5 (not vintage). Right on top of the manual in chapter "getting started" there is a subchapter "Spock example project".

I faced two error when I run my retrofit test with robolectric befor the test starts

I have written this test in test pakage, for test of a retrofit class, but even before test stars,in addition to unknownable "constants" in #Config, this error is shown:
#Config(constants = BuildConfig.class, sdk =21, manifest="app/manifests/AndroidManifest.xml")
#RunWith(RobolectricTestRunner.class)
public class MultiFactorAPITest {
private MainActivity mainActivity;
#Mock
private MultiFactorAPI mockMultiFactorAPI;
#Captor
private ArgumentCaptor<Callback<List<ValidatePhoneUserResponse>>> callbackArgumentCaptor;
#Before
public void setUp() {
MockitoAnnotations.initMocks(this);
ActivityController<MainActivity> controller = Robolectric.buildActivity(MainActivity.class);
mainActivity = controller.get();
// Then we need to swap the retrofit api impl. with a mock one
// We store our Retrofit api impl as a static singleton in class RestClient, hence:
RestClient.setApi(mockMultiFactorAPI);
controller.create();
}
The error is:
Annotation processors must be explicitly declared now. The following dependencies on the compile classpath are found to contain annotation processor. Please add them to the annotationProcessor configuration.
- auto-service-1.0-rc4.jar (com.google.auto.service:auto-service:1.0-rc4)
Alternatively, set android.defaultConfig.javaCompileOptions.annotationProcessorOptions.includeCompileClasspath = true to continue with previous behavior. Note that this option is deprecated and will be removed in the future.
See https://developer.android.com/r/tools/annotation-processor-error-message.html for more details.
I've added these lines to gargle to:
dependencies {
implementation 'org.robolectric:robolectric:4.3'
implementation "org.mockito:mockito-core:1.10.19"
implementation 'org.hamcrest:hamcrest-library:1.1'
}
in gradle.Madule:
android{
testOptions {
unitTests {
includeAndroidResources = true
}
} }
in gradle.app:
dependencies{
classpath 'org.robolectric:robolectric-gradle-plugin:1.0.1'
}
in gradle.propertice:
android.enableUnitTestBinaryResources=true
android.enableAapt2=false
my problem solved by putting this code in my app.gradle :
dependencies{
implementation 'com.squareup.retrofit2:retrofit:2.5.0'
implementation 'com.squareup.okhttp3:mockwebserver:3.6.0'
}
and
1) find the location of of your .gradle folder, in Android Studio goto File->Settings and type "gradle" in the search box. You will be able to pick up the correct path there
2)Remove the .gradle directory (mine's location was C:\Users\UserName.gradle), and restart android studio. It will automatically create a new one.
from Android studio: build project error - Failed to complete Gradle execution

Robolectric PowerMock java.lang.NoClassDefFoundError error while running a test

I want to integrate powermock to test firebase logic. I tried to run a test and got this:
java.lang.NoClassDefFoundError: org/mockito/cglib/proxy/MethodInterceptor
Here is my app.gradle:
testCompile 'junit:junit:4.12'
testCompile "org.powermock:powermock-module-junit4:1.7.0"
testCompile "org.powermock:powermock-module-junit4-rule:1.7.0"
testCompile "org.powermock:powermock-api-mockito:1.7.0"
testCompile "org.powermock:powermock-classloading-xstream:1.7.0"
testCompile "org.robolectric:robolectric:3.4.2"
testCompile 'org.mockito:mockito-core:2.1.0'
Here is my test:
#RunWith(RobolectricTestRunner.class)
#Config(constants = BuildConfig.class)
#PowerMockIgnore({ "org.mockito.*", "org.robolectric.*", "android.*" })
#PrepareForTest({FirebaseAuth.class, FirebaseDatabase.class})
public class LoginTest {
#Before
public void setUp() {
PowerMockito.mockStatic(FirebaseAuth.class);
Mockito.when(FirebaseAuth.getInstance()).thenReturn(Mockito.mock(FirebaseAuth.class));
}
#Test
public void test() {
}
}
You are using 'org.mockito:mockito-core:2.1.0' with "org.powermock:powermock-api-mockito:1.7.0".
To use PowerMock with Mockito 2 the "org.powermock:powermock-api-mockito2:1.7.0" should be used.
You need the cglib library in your class path.
My solution is to always download a "complete" powermock ZIP from here. Those ZIP files contain everything you need in order to get going with PowerMock.

Ignore java code from debug library

On my project I have a Stetho Library that I use just in debug compile. But when I try to generate a release apk, it returns an error when compile javacode saying that the Stetho library couldn`t be found.
build.gradle
//Stetho Library
debugCompile 'com.facebook.stetho:stetho:1.2.0'
debugCompile('com.parse:parseinterceptors:0.0.1') {
exclude group: 'com.parse.bolts';
exclude group: 'com.parse';
}
StethoHelper.java
public class StethoHelper {
public static void initialize(Context context) {
com.facebook.stetho.Stetho.initialize(
com.facebook.stetho.Stetho.newInitializerBuilder(context)
.enableDumpapp(com.facebook.stetho.Stetho.defaultDumperPluginsProvider(context))
.enableWebKitInspector(com.facebook.stetho.Stetho.defaultInspectorModulesProvider(context))
.build());
}
public static void addInterceptor(Parse.Configuration.Builder builder) {
builder.addNetworkInterceptor(new com.parse.interceptors.ParseStethoInterceptor());
}
}
Ok, this error makes sense, but how can I suppress this error without have to comment my code?
you are using debugCompile 'com.facebook.stetho:stetho:1.2.0' which will work only for debug apk. you can change it to compile 'com.facebook.stetho:stetho:1.2.0'.
though you should not enable stetho in release build for security reasons.
Here is simple documentation for your reference.
http://littlerobots.nl/blog/stetho-for-android-debug-builds-only/

Gradle project does not build when I add RoboBlender

I have added RoboGuice 3 dependency into my gradle build file it compiles and runs, however the application crashes because of NoClassDefFoundError: AnnotationDatabaseImpl. Did some research that suggested that RoboBlender was necessary to generate the definition (I'm familiar with RoboGuice 2 which does not require RoboBlender) but when I add RoboBlender the project no longer builds.
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:21.0.3'
compile 'com.android.support:cardview-v7:21.0.+'
compile 'com.android.support:recyclerview-v7:21.0.+'
compile 'com.koushikdutta.urlimageviewhelper:urlimageviewhelper:1.0.4'
compile 'de.hdodenhof:circleimageview:1.2.1'
compile 'com.getbase:floatingactionbutton:1.4.0'
compile 'de.hdodenhof:circleimageview:1.2.1'
compile 'org.twitter4j:twitter4j-core:4.0.2'
compile files('libs/json-me.jar')
compile files('libs/twitter_api_me-1.9.jar')
compile('ch.acra:acra:4.5.0') {
exclude group: 'org.json'
}
compile 'org.roboguice:roboguice:3.0.1'
provided 'org.roboguice:roboblender:3.0.1'
}
Build Error:
Error:Execution failed for task ':app:compileDebugJava'.
java.lang.ClassCastException: com.sun.tools.javac.code.Type cannot be cast to javax.lang.model.type.DeclaredType
l>Gradle's dependency cache may be corrupt (this sometimes occurs after a network connection timeout.)
Re-download dependencies and sync project (requires network)The state of a Gradle build process (daemon) may be corrupt. Stopping all Gradle daemons may solve this problem.
Stop Gradle build processes (requires restart)In the case of corrupt Gradle processes, you can also try closing the IDE and then killing all Java processes.
Whats causing this and how can I fix it?
This kind of error can be caused by using #Inject incorrectly as in the following example:
public class Foo {
#Inject
public Foo(Context context, int code) {
//this won't work because of the primitive in the constructor
//and the #Inject annotation are being used together
}
}
RoboBlender will not be able construct the database because of being unable to cast the primitive as a declared type.
Hence, your error message
java.lang.ClassCastException: com.sun.tools.javac.code.Type cannot be cast to javax.lang.model.type.DeclaredType
means that the primitive (com.sun.tools.javac.code.Type) cannot be cast into a reference type javax.lang.model.type.DeclaredType
Instead, you need to write a Provider:
public class FooProvider implements Provider<Foo> {
Context context;
private static int CODE = 1;
#Inject
public FooProvider(Context context) {
this.context = context;
}
#Override
public Foo get() {
return new Foo(context, CODE);
}
}
and bind Foo to that provider in the module
binder.bind(Foo.class).toProvider(FooProvider.class);
and remove the #Inject from the constructor of Foo.
I suggest you traverse your object graph and look for #Inject annotations on constructors with primitives in them. Delete the annotations and write providers for them as above. RoboBlender will correctly build the AnnotationsDatabaseImpl and your project will compile.
Well I found a workaround, I just disabled AnnotationDatabase processing and removed RoboBlender dependency and that fix my problem. I would still like to know why I'm having this problem in the first place.
I had the same issue and in my case, having a class with 2 constructors:
#Inject
public PaymentSelectionDialog(Context context) {
this.context = context;
}
#Inject
public PaymentSelectionDialog(Context context, PaymentSelectable paymentSelectable) {
this.context = context;
this.paymentSelectable = paymentSelectable;
I had no problems using first constructor, but when I was instantiating my object using second constructor i have that problem. So the problem is that Roboguice is trying to inject an object that implements PaymentSelectable interface but this object is not defined in any module.
Maybe you are using a constructor with a reference that you are not defining in any of your modules.
Hope it helps!

Categories

Resources