I am trying to write unit tests for a Cloud Endpoints backend, specifically using Datastore. (Unit testing without access to any specific Android modules is working as expected.)
Per this question, I added the following to my backend's build.gradle:
testCompile 'com.google.appengine:appengine-api-labs:1.9.8'
testCompile 'com.google.appengine:appengine-api-stubs:1.9.8'
testCompile 'com.google.appengine:appengine-testing:1.9.8'
testCompile 'junit:junit:4.12+'
My code is minimized from this tutorial and located at backend/src/test/java/<package>:
import com.google.appengine.tools.development.testing.LocalDatastoreServiceTestConfig;
import com.google.appengine.tools.development.testing.LocalServiceTestHelper;
import org.junit.Test;
import static junit.framework.Assert.assertTrue;
public class ExampleDatastoreTest {
private final LocalServiceTestHelper datastoreHelper =
new LocalServiceTestHelper(new LocalDatastoreServiceTestConfig());
#org.junit.Before
public void setUp() throws Exception {
datastoreHelper.setUp();
}
#org.junit.After
public void tearDown() throws Exception {
datastoreHelper.tearDown();
}
#Test
public void testExample() {
assertTrue(true);
}
}
I am getting NoClassDefFoundError when I call tearDown on my LocalServiceTestHelper.
Per that tutorial, I still need to include:
${SDK_ROOT}/lib/impl/appengine-api.jar
${SDK_ROOT}/lib/impl/appengine-tools-sdk.jar
Using File > Project Structure in Android Studio 1.2.2, I found these options:
testCompile 'com.google.appengine:appengine-tools-sdk:1.9.25'
testCompile 'com.google.appengine:appengine-api-1.0-sdk:1.9.25'
testCompile 'com.google.appengine:appengine:1.9.25'
The appengine-tools-sdk looks good, but I don't seem to be able to find appengine-api. The two I listed above are the closest I found. I continue to get the same error.
What am I missing here?
Related
I am using java's manifold extension library for junit testing and i cant figure what i am doing wrong even after following exactly their docs.
// My Class
package practice_junit;
public class SomeClass
{
public SomeClass()
{
}
private String get_string()
{
return "ABCDE";
}
}
// My Unit Test Class -- first way
package practice_junit;
import manifold.ext.api.Jailbreak;
import static org.junit.Assert.assertEquals;
import org.junit.Test;
public class SomeClassTest
{
public SomeClassTest()
{
}
#Test
public void assert_equals_true_test()
{
#Jailbreak SomeClass sc = new SomeClass();
assertEquals("Error equals","ABCDE",sc.get_string());
}
}
// My Unit Test Class -- second way
package practice_junit;
import manifold.ext.api.Jailbreak;
import static org.junit.Assert.assertEquals;
import org.junit.Test;
public class SomeClassTest
{
public SomeClassTest()
{
}
#Test
public void assert_equals_true_test()
{
SomeClass sc = new SomeClass();
assertEquals("Error equals","ABCDE",sc.jailbreak().get_string());
}
}
In both the cases i am getting same error log :-
PS C:\Users\> gradle build
> Task :compileTestJava FAILED
C:\Users\SomeClassTest.java:19: error: get_string() has private access in SomeClass
assertEquals("Error equals","ABCDE",sc.get_string());
^
1 error
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':compileTestJava'.
> Compilation failed; see the compiler error output for details.
* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.
* Get more help at https://help.gradle.org
BUILD FAILED in 1m 9s
3 actionable tasks: 1 executed, 2 up-to-date
I am using gradle and manifold extension dependency as compile group: 'systems.manifold', name: 'manifold-ext', version: '2019.1.12' from https://mvnrepository.com/artifact/systems.manifold/manifold-ext/2019.1.12
What version of Java are you using? If Java 9 or later, are you using the JPMS (modules)? If you post your Gradle script, I can help you set it up properly. Better, post an issue on the manifold github with a link to your project. It may be that the --module-path is not explicitly set, which is a very common problem with Gradle scripts using Java 9+. Here's are the relevant bits:
dependencies {
compile group: 'systems.manifold', name: 'manifold-ext', version: '2019.1.12'
testCompile group: 'junit', name: 'junit', version: '4.12'
// Add manifold to -processorpath for javac (for Java 9+)
annotationProcessor group: 'systems.manifold', name: 'manifold-ext', version: '2019.1.12'
}
compileJava {
doFirst() {
// If you DO NOT define a module-info.java file:
options.compilerArgs += ['-Xplugin:Manifold']
// if you DO define a module-info.java file:
//options.compilerArgs += ['-Xplugin:Manifold', '--module-path', classpath.asPath]
//classpath = files()
}
}
The Manifold project tends to use Maven everywhere; the Gradle setup docs are not as polished.
I was learning how to use Micronaut to create REST services but something I can't see is wrong with my tests settings and whatever I change in my code or in gradle I always get an annoying 'Page not found' error when running the tests but not when the application is running normally.
I have a class named App in the package br.com.myproject. In this class I have only the main method, as follows:
public static void main(final String[] args) {
Micronaut.run(App.class);
}
In a subpackage br.com.myproject.controllers I have a class HelloController annotated with #Get("/hello") that should respond with a single "Hello, World!" text and it does normally when I access it through the browser:
package br.com.myproject.controllers;
#Controller("/hello")
public class HelloController {
#Get("/")
#Produces(MediaType.TEXT_PLAIN)
public String index() {
return "Hello, World!";
}
}
In the tests directory, I have the class HelloControllerTest that should assure my /hello endpoint works properly. But unfortunately, my test is failing with a PageNotFound exception.
My class test is as follows:
package br.com.myproject.controllers;
public class HelloControllerTest {
private static EmbeddedServer server;
private static HttpClient client;
#BeforeClass
public static void setupServer() {
server = ApplicationContext.run(EmbeddedServer.class);
client = server
.getApplicationContext()
.createBean(HttpClient.class, server.getURL());
}
#AfterClass
public static void stopServer() {
if (client != null)
client.stop();
if (server != null)
server.stop();
}
#Test
public void testHello() throws Exception {
HttpRequest<String> httpRequest = HttpRequest.GET("/hello");
String body = client.toBlocking().retrieve(httpRequest);
Assert.assertNotNull(body);
Assert.assertEquals(body, "Hello, World!");
}
}
And, for last, my gradle settings:
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.github.jengelman.gradle.plugins:shadow:4.0.3'
classpath 'io.spring.gradle:dependency-management-plugin:1.0.6.RELEASE'
classpath 'net.ltgt.gradle:gradle-apt-plugin:0.15'
}
}
plugins {
id 'io.spring.dependency-management' version '1.0.6.RELEASE'
id 'com.github.johnrengelman.shadow' version '4.0.3'
id 'application'
id 'java'
id 'net.ltgt.apt-idea' version '0.15'
}
group 'br.com.myproject'
version '1.0.0-SNAPSHOT'
sourceCompatibility = 1.8
repositories {
mavenLocal()
mavenCentral()
maven { url "https://plugins.gradle.org/m2/" }
}
dependencies {
annotationProcessor 'io.micronaut:micronaut-inject-java:1.0.0'
compile 'io.micronaut:micronaut-http-client:1.0.0'
compile 'io.micronaut:micronaut-http-server-netty:1.0.0'
compile 'io.micronaut:micronaut-inject:1.0.0'
compile 'io.micronaut:micronaut-runtime:1.0.0'
compileOnly 'io.micronaut:micronaut-inject-java:1.0.0'
runtime 'ch.qos.logback:logback-classic:1.2.3'
testCompile 'junit:junit:4.12'
testCompile 'io.micronaut:micronaut-inject-java:1.0.0'
}
shadowJar {
mergeServiceFiles()
}
mainClassName = 'br.com.myproject.App'
Both my tests and my gradle settings were written based on a code example in Micronaut documentation (this one). And somehow the tests in the code example works properly.
For instance, these are what I tried before asking here:
Changed the versions of dependencies to match versions in code example: it didn't work;
Put all classes under same package (br.com.myproject): it didn't work;
Copy/paste the gradle settings of the example code into my gradle settings and changing the package names properly: it didn't work;
Print out the URL used in the test just to check if it is correct: it is correct, but still 'Page not found' is thrown.
Everything works fine, however, when I run the application and type the address into the browser.
I have googled the keywords "micronaut test page not found" and similars but I found no useful articles that helped me to fix this error.
Just to mention: I am not completely familiar with gradle configuration and thus I suspect I might be lacking something here.
Does anyone have any idea what I may be missing?
I appreciate any tip.
Thanks =)
See the project at https://github.com/jeffbrown/jonathansouzanotfound. I have pasted your code directly into that project (and added missing import statements) and the test passes.
$ ./gradlew clean test
> Task :compileJava
...
BUILD SUCCESSFUL in 4s
5 actionable tasks: 5 executed
#Get("/")
#Produces (MediaType.TEXT_PLAIN)
public String index(){
return "Hello World";
}
Referred from Jeff's comment and answered it here to make it more visible
Make sure annotation processing is enabled in the IDE if you running the tests through IDE.
The error message I receive:
java.lang.IllegalStateException: Could not initialize plugin:
interface org.mockito.plugins.MockMaker
The code in question:
List<String> mockList = mock(List.class);
The build.gradle dependency:
dependencies {
testCompile group: 'junit', name: 'junit', version: '4.12'
def mockito_version = 'latest.release'
// For local unit tests on your development machine
testCompile "org.mockito:mockito-core:$mockito_version"
}
I have tried looking at other people with the same issue and I keep getting references to PowerMock. I have no idea what that means, so if this is a duplicate I apologize. It just seems like no other question had a solution that resolved my issue. The library is imported properly, as I do not have any compilation errors. Any help would be greatly appreciated.
i tried to create a new project and test this out. below is how my depdencies in gradle file looks:
dependencies {
testCompile group: 'junit', name: 'junit', version: '4.12'
testCompile "org.mockito:mockito-core:2.+"
}
below is my test class:
import org.junit.Assert;
import org.junit.Test;
import java.util.List;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
public class TestList {
#Test
public void Test(){
List<String> myList = mock(List.class);
when(myList.get(0)).thenReturn("hello world");
Assert.assertEquals("hello world",myList.get(0));
}
}
this works.
I am unable to mock a Kotlin final class using Mockito 2. I am using Robolectric in addition.
This is my test code:
#RunWith(RobolectricTestRunner.class)
#Config(constants = BuildConfig.class, sdk = 21)
public class Test {
// more mocks
#Mock
MyKotlinLoader kotlinLoader;
#Before
public void setUp() {
MockitoAnnotations.initMocks(this);
}
}
The test fails when we try to initialise the mocks in the setUp() method.
In addition, I am using the following gradle dependencies in my code:
testCompile 'org.robolectric:robolectric:3.3.2'
testCompile 'org.robolectric:shadows-multidex:3.3.2'
testCompile 'org.robolectric:shadows-support-v4:3.3.2'
testCompile("org.powermock:powermock-api-mockito2:1.7.0") {
exclude module: 'hamcrest-core'
exclude module: 'objenesis'
}
testCompile 'junit:junit:4.12'
testCompile 'org.mockito:mockito-inline:2.8.9'
All other unit tests pass using this configuration but as soon as I try to mock the Kotlin class it throws the following error:
Mockito cannot mock/spy because :
- final class
Please note I am using Mockito version 2 and I am using the inline dependency which automatically enables the ability to mock final classes.
PowerMock implements its own MockMaker which leads to incompatibility with Mockito mock-maker-inline, even if PowerMock is just added as a dependency and not used. If two org.mockito.plugins.MockMaker exist in path then any only one can be used, which one is undetermined.
PowerMock can however delegate calls to another MockMaker, and for then tests are run without PowerMock. Since PowerMock 1.7.0 this can be configured with using the PowerMock Configuration.
The MockMaker can be configured by creating the file org/powermock/extensions/configuration.properties and setting:
mockito.mock-maker-class=mock-maker-inline
Example of using Mockito mock-maker-inline with PowerMock: https://github.com/powermock/powermock-examples-maven/tree/master/mockito2
Since Mockito 2.1.0 there is a possibility to mock final types, enums, and final methods. It was already mentioned in the comments to the original question.
To do this, you’ll need to create a folder (if dont exist) test/resources/mockito-extensions and add there file with the name org.mockito.plugins.MockMaker and this line:
mock-maker-inline
Links to documentation and tutorial
mock-maker-inline works as is pointed out in other answers. But It's really slow. You can use the all-open plugin to avoid this problem.
To do so you need:
Create an Annotation:
annotation class Mockable
Activate all-open in your build.gradle file:
dependencies {
classpath "org.jetbrains.kotlin:kotlin-allopen:$kotlin_version"
}
apply plugin: 'kotlin-allopen'
allOpen {
annotation('com.example.Mockable')
}
Annotate the classes that you want to mock:
#Mockable
class Foo {
fun calculateTheFoo(): Int {
sleep(1_000) // Difficult things here
return 1
}
}
If you want more information you can read my blog post where I explain this with more details: Mocking Kotlin classes with Mockito — the fast way
Try adding this below dependency to your build.gradle.
testImplementation 'org.mockito:mockito-inline:2.8.47'
Replace with your mockito version instead of 2.8.47. This will help you to avoid using powermock for the issue.
please look into the below link to know how this thing works.
How to mock a final class with mockito
You may use Powermock for this, for example:
import static org.powermock.api.mockito.PowerMockito.mock;
import static org.powermock.api.mockito.PowerMockito.spy;
import static org.powermock.api.mockito.PowerMockito.when;
#RunWith(RobolectricTestRunner.class)
#Config(constants = BuildConfig.class, sdk = 21)
#PowerMockIgnore({ "org.mockito.*", "org.robolectric.*", "android.*" })
#PrepareForTest({FinalClass1.class, FinalClass2.class})
public class Test {
#Rule
public PowerMockRule rule = new PowerMockRule();
... // your code here
}
Let us program to interfaces, not implementations. You can extract an interface, use it in your code, and mock it. For example, the following will not work:
import com.nhaarman.mockito_kotlin.mock
class MyFinalClass {...}
(snip)
private val MyFinalClass = mock()
So let us extract an interface:
class MyFinalClass : MyInterface {...}
(snip)
private val MyInterface = mock()
Because in kotlin all classes are final by default.
You should also consider adding open to the class declaration.
Example: open class MyClasss{}
I'm developing an SDK and I'm trying to perform UnitTests on it.
This means most of the my project is pure java code which involves Android code in some places.
I want to perform UnitTest on my SDK and I decided to with with Roboelectric, Mockito and PowerMock (for static methods mocks).
Everything works fine except one issue:
When my test calls any method which contains Android class, my test crashes (due to Stub issues).
I know I can't test Activity,Views and more classes but the problem is I get RuntimeException even when my functions contain a use with Log class.
How can I handle this issue?
I decided to work with pure UnitTest because most of my code doesn't contain Android classes except of Log class. By using pure java UnitTest I don't need any device to run and as a result I can perform multi test task on the same time.
I've tried to include the android.jar file in my gradle but it didn't work.
What should I do?
1. Stick to pure Java UnitTest: so how can I ignore/import the Log instructions.
2. Move to Android test framework: What is the best for my needs?
Here is a section in my gradle file relevant for the tests:
robolectric {
// configure the set of classes for JUnit tests
include '**/*UnitTest.class'
// confgure max heap size of the test JVM
maxHeapSize = '2048m'
// configure the test JVM arguments
jvmArgs '-XX:MaxPermSize=512m', '-XX:-UseSplitVerifier'
// configure whether failing tests should fail the build
ignoreFailures true
// use afterTest to listen to the test execution results
afterTest { descriptor, result ->
println "Executing test for {$descriptor.name} with result: ${result.resultType}"
}
}
dependencies {
androidTestCompile 'org.robolectric:robolectric:2.3'
androidTestCompile 'junit:junit:4.10'
androidTestCompile 'org.mockito:mockito-core:1.8.5'
androidTestCompile 'org.powermock:powermock-mockito-release-full:1.4.9'
androidTestCompile files('../libs-test/json.jar')
}
And here is an Example of a TestCase class:
import android.util.Log;
import junit.framework.TestCase;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import org.junit.Test;
import org.json.JSONObject;
import static org.powermock.api.mockito.PowerMockito.when;
#RunWith(PowerMockRunner.class)
#PrepareForTest(StaticInClass.class)
public class ClassExampleUnitTest extends TestCase{
#Test
public void testSimple(){
Log.d("UnitTest", "test");
assertTrue(true);
}
}
When you run with PowerMockRunner, you aren't actually running through robolectric. Normally you would run like this, when you need the robolectric framework:
#RunWith(RobolectricTestRunner.class)