Android Studio 3 beta 2 ClassNotFound in kotlin unit tests - android-studio

I am using Android Studio 3.0 beta 2, converted an existing project to gradle plugin 3.0.0-beta2
When I try to run an existing unit test written in kotlin I get 'java.lang.NoClassDefFoundError: com/other/domain/CollectionItem'
The test itself is very simple:
import org.junit.Test
import org.junit.Assert.*
class CollectionViewModelTest {
#Test
fun getItemsWithManyItemsWillReturnCollectionItemViewModels() {
val collectionItems = listOf(CollectionItem(42, "Item1", CollectionItemType.COLLECTION, ""), CollectionItem(43, "Item2", CollectionItemType.COLLECTION, ""), CollectionItem(44, "Item3", CollectionItemType.COLLECTION, ""))
val collection = Collection(45, "Home", "Home collection", collectionItems, 42)
val collectionViewModel = CollectionViewModel(collection)
assertTrue(collectionViewModel.items.first().isFirst)
assertFalse(collectionViewModel.items.first().isLast)
assertFalse(collectionViewModel.items[1].isFirst)
assertFalse(collectionViewModel.items[1].isLast)
assertTrue(collectionViewModel.items.last().isLast)
assertFalse(collectionViewModel.items.last().isFirst)
}
}
It works when I run it from the terminal using ./gradlew
Any ideas why this can happen?
Edit:
This seems to happen only when the test requires classes from other library projects.
In this case CollectionItem is part of another library in the same project and it's included in the gradle file via implementation project(':domain')
Edit
It might also be worth mentioning that domain module is pure java
Edit
Figured out the problem is when the library (domain) has classes written in kotlin, those classes will throw NoClassDefFoundError in unit test's only.

Related

Kotlin / Gradle DSL integration to manage dependency version variables

Kotlin / Gradle DSL integration to manage dependency version variables
My question is about the best way to manage dependency version variables in IntelliJ Idea / Android Studio using Gradle
Kotlin DSL
The secondary purpose is to have the IDE perform version upgrades upon clicking the suggestion to change to newer
version automatically instead of manually editing the versioning file entry.
the simple way
definition
build.gradle.kts
plugins {
application
kotlin("jvm") version "1.7.10"
}
dependencies {
implementation("io.ktor:ktor-server-core-jvm:2.1.1")
}
Comments
This is working but "clumsy" and does not comply to single source of truth (SSOT)
I have seen several ways that attempt having a SSOT for the dependency versions
by Project
Definition
gradle.properties
ktor_version = 2.1.0
kotlin_version = 1.7.10
build.gradle.kts
val ktor_version: String by project // NOTE the complaint Property name 'ktor_version' should not contain underscores
val kotlin_version: String by project
plugins {
application
kotlin("jvm") version "1.7.10" // NOTE you cannot replace this with the variable!
// 'val kotlin_version: String' can't be called in this context by implicit receiver. Use the explicit one if necessary
}
dependencies {
implementation("io.ktor:ktor-server-core-jvm:$ktor_version")
}
Comments
This does not update the suggested version numbers via "Project Structure/Suggestions" in AS/IJ
my inline NOTES indicate several issues with this method!
by buildSrc java Module
Definition
object Ktor {
private const val ktorVersion = "2.0.0"
const val core = "io.ktor:ktor-client-core:${ktorVersion}"
const val android = "io.ktor:ktor-client-android:${ktorVersion}"
}
implementation in build.gradle.kts
implementation(Ktor.android)
Comments
This does not update the suggested version numbers via "Project Structure/Suggestions" in AS/IJ, is seemed to
be totally de-coupled, and it is a nightmare to manually find and update the versions manually to the latest!
However: doing it by buildSrc java Module makes it much easier to re-use in other projects
by Gradle Version Catalogs
Definition
libs.versions.toml // in the gradle directory next to wrapper
[versions]
plugin-kotlin = "1.7.10"
ktor = "2.1.0"
[libraries]
plugin-kotlin = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "plugin-kotlin" }
ktor-client-core = { module = "io.ktor:ktor-client-core", version.ref = "ktor" }
[bundles]
plugins = ["plugin-android", "plugin-kotlin", "plugin-kotlin-serialization", "plugin-sqldelight"]
implementation in build.gradle.kts(project)
buildscript {
repositories {
gradlePluginPortal()
google()
mavenCentral()
}
dependencies {
classpath(libs.bundles.plugins)
}
}
implementation in build.gradle.kts(shared)
sourceSets {
val commonMain by getting {
dependencies {
implementation(libs.ktor.client.core)
}
}
}
Comments
This is by far the favorite of mine, the reason is clear, it allows SSOT, and it allows grouping/bundling to make
"sets" that is more understandable later on
However!
This does not update the suggested version numbers via "Project Structure/Suggestions" in AS/IJ
it is a nightmare to manually find and update the versions manually to the latest!
Main question
Is there a better way of managing dependency versions?
Is there a way that works inside the IDE AS/IJ suggestions to update the versions correctly at the definition
location?

Groovy how can I build a custom library and use it in a project as dependency

I have a set of code procedures I use in a lot of places and I'm trying to basically move it to a library.
So I created my library with some unit test and everything was looking promising and at least working localy..
When I went to my project and deleted the files locally and then try to import them from my library as a dependency the code does not work.
I always get this kind of error
Class does not define or inherit an implementation of the resolved method abstract getProperty(Ljava/lang/String;)Ljava/lang/Object; of interface groovy.lang.GroovyObject.
I'm definitely not an expert on groovy but basically I use it in my Jenkins and Gradle for pipelines and some basic packaging or environment deployments.
I can show my class:
class ConsoleRow implements Comparable {
...
final Integer priority
final String rowStatus
final String message
final String rowReportClass
ConsoleRow(Integer priority, String status, String msg, String rowC) {
this.priority = priority
this.rowStatus = status
this.message = msg
this.rowReportClass = rowC
}
#Override
int compareTo(Object o) {
return this.priority <=> ((ConsoleRow) o).priority
}
The line that gives me the error is this actual compareTo when trying to do the "this.priority"
Caused by: java.lang.AbstractMethodError: Receiver class com.abc.insight.jenkins.ConsoleRow does not define or inherit an implementation of the resolved method abstract getProperty(Ljava/lang/String;)Ljava/lang/Object; of interface groovy.lang.GroovyObject.
at com.abc.insight.jenkins.ConsoleRow.compareTo(ConsoleRow.groovy:24)
at com.abc.insight.jenkins.ConsoleOutputHtmlBuilder.processOutput(ConsoleOutputHtmlBuilder.groovy:115)
at com.abc.insight.jenkins.ConsoleOutputHtmlBuilder.processOutput(ConsoleOutputHtmlBuilder.groovy)
at com.abc.insight.jenkins.ConsoleOutputHtmlBuilder.buildReport(ConsoleOutputHtmlBuilder.groovy:20)
at com.abc.insight.jenkins.ConsoleOutputHtmlBuilder$buildReport.call(Unknown Source)
at build_e548mc0tqjmi822clitlsycdk.runReport(C:\dev\repo\insight\insight-health-check\data-foundation\smoke-test\build.gradle:77)
The calling function is just trying to sort a list of those objects
List<ConsoleRow> outputRows = []
...
return outputRows.sort()
The part that gets me really confused is that if instead of importing the library as a dependency I just do this directly in this repo and put my sources in my buildSrc\src\main\groovy\com\abc\insight the code works fine...
So I really think it might be how I package and publish my library that might be wrong.
I'm really sure this is some basic error on my part because I never did a groovy library before but somehow I can't make it work.
It might be that my publication is just wrong, on my library side I'm using this plugins to do the publishing.
plugins {
id 'groovy'
id 'java-library'
id 'base'
}
publishing {
publications {
maven(MavenPublication) {
from components.java
}
}
}
I tried to change components.groovy but somehow it does not work.
Any ideas or tips, I think my question probably is showing some really lack of know-how on groovy but looking at the documentation and examples I could not figure it out.
Doing some debug in my IDE the compareTo that generates the exception looks like this.
public int compareTo(Object o) {
CallSite[] var2 = $getCallSiteArray();
return ScriptBytecodeAdapter.compareTo(this.priority, var2[0].callGroovyObjectGetProperty((ConsoleRow)ScriptBytecodeAdapter.castToType(o, ConsoleRow.class)));
}
I tried following this guide and code structure when doing moving the code to a library
https://docs.gradle.org/current/samples/sample_building_groovy_libraries.html
Thanks for any feedback
p.s: My code might look weird, I tried first to have everything with the def blablabla but I was having some issues with typecasting but I don't think this would be the reason for the problem I'm facing.
Anyway I got a look at the generated code in my IDE and I see a lot of get methods just no idea where they expected this getProperty from
Ok this was definitely a user error.
I am using distribution version of gradle 6.5.1
When I did the gradle init to bootstrap my project I was provided with the dependency of gradle groovy-all version 2.5.11
implementation group: 'org.codehaus.groovy', name: 'groovy-all', version: '2.5.11'
I thought that was a mistake and just updated to the latest version.
implementation group: 'org.codehaus.groovy', name: 'groovy-all', version: '3.0.9'
Now the problem is that the project in which I'm using the library is also running with gradle 6.5.1 so probably this version missmatch between compiple and usage was causing the problem.
By reverting to the correct version suggested by gradle the problem is gone.

Kotlin unresolved reference linkedListOf

Following this post http://obviam.net/index.php/libgdx-and-kotlin/ I
created a project, and edited using Atom. It compiles, and runs on an android device. I want to convert to AndroidStudio for better tooling.
I'm using AndroidStudio 1.5.1, and it says I have the latest version of the kotlin plugin. I created a new project using the LibGDX setup program, imported into AdroidStudio, converted the main class to kotlin, everything works. Then I pasted in my existing my code, and when I build, this line:
val bullets:MutableList<NewBullet> = linkedListOf()
gets this error:
Error:(19, 42) Unresolved reference: linkedListOf
When I select Tools -> Kotlin -> Configure it says 'All modules with Kotlin files are configured'.
I've also tried importing the existing project into AndroidStudio, and the result is the same issue.
As said in the change log of Kotlin 1.0 RC, linkedListOf has been deprecated and is not available now. The article you referenced uses Kotlin 1.0 Beta, which is older.
To create a LinkedList<T> from varargs, you can pass a listOf(...) to the constructor:
val bullets: MutableList<SomeType> = LinkedList(listOf(item1, item2))
or write your own linkedListOf:
fun <T> linkedListOf(vararg items: T) = LinkedList<T>().apply {
for (i in items) { add(i) }
}

Is JUnit really unable to find my test class in android studio?

I read the solution to How to run a simple JUnit4 test in Android Studio 1.1? and verified my gradle plugin version is greater than 1.1
Right Clicking my junit 4 test class and selecting run gives this error in android studio:
Cannot find class com.me.android.javamodule.MyTestClass
My android proj dir looks like:
In module "app":
src-->main
src-->test-->java-->com.me.android.working contains WorkingTest.java
src-->test-->java-->com.me.android.javamodule contains MyTestClass.java
"javamodule" is a regular java module that the app module depends on, it is a sibling to the "app" module.
I don't think the error is accurate because I copied "MyTestClass.java" into com.me.android.working, which contains WorkingTest.java, a Junit4 test that CAN run. Android Studio still complains with the same error.
Here is MyTestClass.java
package com.me.android.javamodule;
import org.junit.Before;
import org.junit.Test;
public class MyTestClass {
private Solver solver;
#Before
public void init() {
solver = new Solver();
}
#Test
public void testReverse() {
assertTrue(solver.parseStr("woof").equals("foow"));
}
}
This worked for me:
right click src and select New Directory, call it test
do the same for test and call it java
right click java and select New Package to create a new package like com.application. unit test can go here.

Unit testing in android studio

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.

Resources