I have written some code that manipulates MotionEvent instances, and want to write a unit test for it.
The unit test needs to validate my manipulations only; it does not need to simulate any user actions.
I understand it needs to be an instrumented test to be able to use the methods of MotionEvent; I need the actual methods, not any mocking.
I have defined an instrumented test in the directory src/androidTest/...; however, it still throws the exception
java.lang.RuntimeException: Method obtain in android.view.MotionEvent not mocked.
My build.gradle file for the module has the following entries:
defaultConfig {
...
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
...
dependencies {
implementation 'androidx.appcompat:appcompat:1.3.0'
implementation 'com.google.android.material:material:1.3.0'
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
testImplementation 'junit:junit:4.+'
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
}
The imports in my test class are as follows:
import android.view.MotionEvent;
import org.junit.Test;
import static org.junit.Assert.*;
How can I run this test?
My mistake was as follows.
I initially thought that a local unit test would suffice, since no user action was involved.
It turned out to be wrong: the local unit tests do not get access to the Android methods.
I moved my file containing the test, to the place prescribed for the instrumented tests, /src/androidTest/java/, but did not change the file; this can be seen in my imports.
For this reason it still ran as a local non-instrumented test.
After I realized it, I changed the file to mimic the ExampleInstrumentedTest created by Android studio together with my project. I also deleted the run configuration which was still a local test.
After that Android studio prompted me to create a new run configuration, and the test ran successfully.
Related
I have a Groovy project built using Gradle. The issue happens when I build a jar that has all the dependencies (fatJar), so I'm forced to do everyting in the Java way and get none of the Groovy enhancements
When I try to use any of the Groovy enhancements, I get MissingMethodException, this happens on: (just to give some examples)
new Date().format("yyyyMMddhhmmss")
[1,2,3].average()
Dependencies are:
dependencies {
// Use the latest Groovy version for building this library
implementation 'org.codehaus.groovy:groovy-all:2.5.13'
implementation 'org.codehaus.groovy:groovy-dateutil:2.5.13'
//implementation 'org.codehaus.groovy:groovy-datetime:2.5.13'
// Use the awesome Spock testing and specification framework
testImplementation 'org.spockframework:spock-core:1.3-groovy-2.5'
compile 'log4j:log4j:1.2.17'
// TODO
//implementation 'com.github.ppazos:openEHR-OPT:Tag'
compile fileTree(dir: 'lib', include: '*.jar')
}
This is the project https://github.com/ppazos/testehr
Not really sure what is going on.
I have two libraries with same classes defined in each one. However they have some different contents (methods/constants).
For example:
Library 1:
package com.test.package;
Class A {
// only method signatures
public void methodA() {
}
public void methodB() {
}
}
Library 2:
package com.test.package;
Class A {
public void methodA() {
// some logic that MUST be executed to provide backward compatibility
}
}
My application uses Library 1 and Library 2 and run in devices which have com.test.package.ClassA, but com.test.package.ClassA.methodB() will only exist in newer releases in framework. Said that, I need the Library 1 to be used to compile my application and the Library 2 to execute a different implementation of methodA().
I have tried to do this in Android Studio using .jar and .aar libraries format, but none of them worked for me.
Is it possible to set this configuration in an Android Studio project?
I am building both Library 1 and 2, and I cannot add methodB() in Library 2.
For a simple Java application, you can do this by unlinking the compile and runtime configurations. I set up an example repository here.
The idea is shown in this commit, but can be described as manually resetting the runtime configuration so that it doesn't include the contents of the compile configuration. After doing so, you can just include your runtime library variation in the runtime configuration.
The application's build.gradle becomes something like:
apply plugin: 'application'
mainClassName = 'my.package.MyAppClass'
configurations.runtime.extendsFrom = [] // Reset runtime configuration
dependencies {
compile 'my.group:my.artifact:2.0' // Library 1, with the new method
runtime 'my.group:my.artifact:1.0' // Library 2, without the method
}
For Android, this can be a little more complicated. The problem is that there's no runtime configuration for Android (because you don't execute it on your computer, unless you're using Robolectric or something similar).
I think there are a few workarounds you can probably use, but one initial suggestion would be to create a wrapper library that abstracts away the dependency on the other libraries. This wrapper library you can compile with the newest library version (Library 1, with the new method). You could then include the wrapper library in the Android app while setting it as a non-transitive dependency and including the other library version:
dependencies {
compile 'my.group:my.wrapped.artifact:0.1' {
transitive = false // Don't include dependencies of the wrapper
// i.e., don't include version 2.0 of the lib.
}
compile 'my.group:my.artifact:1.0'
}
This should work because by setting the dependency as non-transitive Gradle doesn't recursively include the dependencies of the wrapper library, so the version used to compile the wrapper isn't included (in theory) in the APK. You can therefore add the old version without causing a conflict.
An example is set up in the same repository, under the Android branch. Firstly, two Java libraries are created. Then an Android library is created to wrap around the compile-time library. An example activity is created to show how using the wrapper library uses the compile-time library. Then, the latest commit shows how the app is configured to use the wrapper library (which compiles with the newest library) but forces the old library to be included instead in the runtime.
Hope this helps =)
I am using newest version of android studio gradle plugin 1.2.3. I am unable to understand how to create unit tests in it; all the available answers are for older version of android. Help me.
first of all you need a different folder structure for your unit tests.
android studio automatically generats the androidTest folder for instrumentation tests, but you can't put your unit tests in there. so you have to create a "test" folder:
- src
-- androidTest //for instrumentation tests
-- main //source code
-- test //for unit tests
use the same package structure for your tests as for the class you want to test.
you can switch in your build variants of android studio between Android Instrumentation Tests and Unit Tests.
depending on your selection test or androidTest folder will be show in your project tab.
finally you have to add junit to your dependencies in gradle:
dependencies {
testCompile 'junit:junit:4.12'
}
the test classes in your test folder can for example look like this:
package package.of.class.to.test
import org.junit.Before;
import org.junit.Test;
...
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
public class TestSomething{
#Before
public void setup(){
// test setup
}
#Test
public void testSomething(){
// your unit tests like these simple examples
assertThat(anyBooleanResult, is(expectedBooleanResult));
assertEquals(anyIntResult, expectedIntResult);
}
}
for further information you can also take a look on this thread.
Classes compiled by buildSrc/build.gradle are not resolved at runtime when they are used in main PROJECT classes.
My Groovy project structure looks like this:
-PROJECT
-buildSrc/
-build.gradle
-/src/main/groovy
- com.company.global.test.report
-src/test/groovy
-build.gradle
Is there something I can add to the top-level PROJECT/build.gradle to allow the classes compiled by it to use the classes compiled by buildSrc/build.gradle?
buildSrc is its own build (not project) that gets executed before the main build. Its sole purpose is to make some classes (plugins, tasks, regular classes) available to the build scripts of the main build. Hence you could call it a "meta-build".
Technically, it would be possible to add the compiled classes of buildSrc to the compile or runtime class path of a project in the main build, but I don't recommend to do it. There is very likely a better way to achieve your goals (but I don't know what those are).
Here is how to do it with Gradle 2.12:
In your_project/buildSrc/build.gradle
task sourcesJar(type: Jar, dependsOn: classes) {
classifier = 'sources'
from sourceSets.main.allSource
}
// Thanks to this, IDE like IntelliJ will provide you with "Navigate to sources"
artifacts {
archives sourcesJar
}
In your_project/build.gradle
ext.buildSrcJars = fileTree("$rootDir/buildSrc/build/libs") { include("*.jar") exclude("*sources.jar")}
// Works in every subproject
dependencies {
compile buildSrcJars
}
I am trying to port some code from the Dropwizard examples from java to groovy.
I see that within java, I can use the following code without any issues:
package com.example.helloworld;
import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;
#Produces(MediaType.APPLICATION_JSON)
public class HelloWorldService{
}
However, with the groovy compiler ( both 1.8 and 2.0.6 ), the class fails to compile with a noClassFoundException around MediaType.APPLICATION_JSON
If I change this code to use the actual string value
#Produces('application/json')
public class HelloWorldService{
}
everything works perfectly.
Are there any differences between the way groovy resolves annotations and the way that java does?
For completeness, this is part of a gradle project and here is my build.gradle ( the file goes under src/groovy/com/example/helloworld )
apply plugin: 'groovy'
// Set our project variables
project.ext {
dropwizardVersion = '0.6.1'
}
repositories {
mavenCentral()
}
dependencies {
compile group: 'com.yammer.dropwizard', name: 'dropwizard-core', version: dropwizardVersion
groovy group: 'org.codehaus.groovy', name: 'groovy-all', version: '1.8.7'
}
The compilation error is:
Caused by: java.lang.RuntimeException:
java.lang.ClassNotFoundException:
com.sun.ws.rs.ext.RuntimeDelegateImpl ... 17 more Caused by:
java.lang.ClassNotFoundException:
com.sun.ws.rs.ext.RuntimeDelegateImpl at
org.gradle.api.internal.tasks.compile.TransformingClassLoader.findClass(TransformingClassLoader.java:47)
The problem is caused by an unfortunate limitation of the Groovy compiler, namely that it uses reflection to access classes on the compile class path. This may in turn trigger other classes to get loaded, which may not be available on the compile class path. Typically (but not always) these are runtime dependencies.
In the concrete case, the Groovy compiler loads javax.ws.rs.core.MediaType via reflection, which ultimately results in com.sun.ws.rs.ext.RuntimeDelegateImpl being loaded via Class.forName (triggered by a static initializer), which isn't on the compile class path. The solution is to put that class on the compile class path. (In the longer run, the solution is to fix the standalone Groovy compiler not to use reflection, and from what I know this is already in the queue.) If your module's transitive dependencies aren't an issue, the simplest way to achieve this is:
dependencies {
compile "com.sun.jersey:jersey-client:1.15"
}
I suspect that the Eclipse Groovy compiler doesn't have this problem because it doesn't use reflection to access the compile class path. I'd expect GMaven to blow up like Gradle, unless it is configured to use the Eclipse compiler (which isn't currently supported by Gradle).