google-developer-training / android-basics-kotlin-cupcake-app

Apache License 2.0
103 stars 163 forks source link

Test ViewModels and LiveData - Fail to perform tests with fail in InstantTaskExecutorRule #58

Closed EleoXDA closed 1 year ago

EleoXDA commented 2 years ago

[URL of codelab

In which task and step of the codelab can this issue be found? page#5 AND solution code

Describe the problem tests fail to accomplish even when I use the solution code. For some reason it fails in InstantTaskExecutorRule part. When checking documentation, it says it is deprecated. I am not sure whether it is related to update in Android Studio that makes it fail.

> Task :app:compileDebugAndroidTestKotlin FAILED
e: D:\Downloads\Android Studio Projects\android-basics-kotlin-cupcake-app-starter\android-basics-kotlin-cupcake-app-starter\app\src\androidTest\java\com\example\cupcake\model\ViewModelTests.kt: (3, 36): Unresolved reference: testing
e: D:\Downloads\Android Studio Projects\android-basics-kotlin-cupcake-app-starter\android-basics-kotlin-cupcake-app-starter\app\src\androidTest\java\com\example\cupcake\model\ViewModelTests.kt: (15, 35): Unresolved reference: InstantTaskExecutorRule

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':app:compileDebugAndroidTestKotlin'.
> Compilation error. See log for more 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 25s
54 actionable tasks: 7 executed, 47 up-to-date

Steps to reproduce? Follow the steps of CodeLab

Versions Android Studio version: 2021.1.1. Patch 2 API version of the emulator: API32

Additional information Include screenshots if they would be useful in clarifying the problem. image

tamarabuilds commented 2 years ago

I had the same problem but solved it by creating a new test/java unit test directory. From the Project Screen, expand app > src and right click, New > Directory: "test/java" Then create a package and then the ViewModelTests.kt class file.

This is the file folder structure in the solution code. Note the folder names: image

Here is my code and how I finally successfully ran the unit tests in my code: image

Thanks for your background research. It does seem that when selecting the new directory "test/java" that one utilizes the appropriate Gradle Source Set for the InstantTaskExecutorRule and testing code. image

Initially I could not resolve the unresolved reference issues with the "androidTest/Java" Directory: image

The tests ran successfully in the test/java directory: image

EleoXDA commented 2 years ago

I had the same problem but solved it by creating a new test/java unit test directory. From the Project Screen, expand app > src and right click, New > Directory: "test/java" Then create a package and then the ViewModelTests.kt class file.

This is the file folder structure in the solution code. Note the folder names: image

Here is my code and how I finally successfully ran the unit tests in my code: image

Thanks for your background research. It does seem that when selecting the new directory "test/java" that one utilizes the appropriate Gradle Source Set for the InstantTaskExecutorRule and testing code. image

Initially I could not resolve the unresolved reference issues with the "androidTest/Java" Directory: image

The tests ran successfully in the test/java directory: image

Thanks a lot! Will test it and report back 👍✌️

EleoXDA commented 2 years ago

I had the same problem but solved it by creating a new test/java unit test directory. From the Project Screen, expand app > src and right click, New > Directory: "test/java" Then create a package and then the ViewModelTests.kt class file.

This is the file folder structure in the solution code. Note the folder names: image

Here is my code and how I finally successfully ran the unit tests in my code: image

Thanks for your background research. It does seem that when selecting the new directory "test/java" that one utilizes the appropriate Gradle Source Set for the InstantTaskExecutorRule and testing code. image

Initially I could not resolve the unresolved reference issues with the "androidTest/Java" Directory: image

The tests ran successfully in the test/java directory: image

Unfortunately that also didn't help. Now, instead of "unresolved reference" I am getting

Delegate runner androidx.test.internal.runner.junit4.AndroidJUnit4ClassRunner for AndroidJUnit4 could not be found.

java.lang.RuntimeException: Delegate runner androidx.test.internal.runner.junit4.AndroidJUnit4ClassRunner for AndroidJUnit4 could not be found.

    at androidx.test.ext.junit.runners.AndroidJUnit4.throwInitializationError(AndroidJUnit4.java:129)
    at androidx.test.ext.junit.runners.AndroidJUnit4.loadRunner(AndroidJUnit4.java:93)
    at androidx.test.ext.junit.runners.AndroidJUnit4.loadRunner(AndroidJUnit4.java:82)
    at androidx.test.ext.junit.runners.AndroidJUnit4.<init>(AndroidJUnit4.java:56)
    at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:490)
    at org.junit.internal.builders.AnnotatedBuilder.buildRunner(AnnotatedBuilder.java:104)
    at org.junit.internal.builders.AnnotatedBuilder.runnerForClass(AnnotatedBuilder.java:86)
    at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:70)
    at org.junit.internal.builders.AllDefaultPossibilitiesBuilder.runnerForClass(AllDefaultPossibilitiesBuilder.java:37)
    at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:70)
    at org.junit.internal.requests.ClassRequest.createRunner(ClassRequest.java:28)
    at org.junit.internal.requests.MemoizingRequest.getRunner(MemoizingRequest.java:19)
    at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.runTestClass(JUnitTestClassExecutor.java:78)
    at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.execute(JUnitTestClassExecutor.java:58)
    at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.execute(JUnitTestClassExecutor.java:38)
    at org.gradle.api.internal.tasks.testing.junit.AbstractJUnitTestClassProcessor.processTestClass(AbstractJUnitTestClassProcessor.java:62)
    at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.processTestClass(SuiteTestClassProcessor.java:51)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:566)
    at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:36)
    at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
    at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:33)
    at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:94)
    at com.sun.proxy.$Proxy2.processTestClass(Unknown Source)
    at org.gradle.api.internal.tasks.testing.worker.TestWorker$2.run(TestWorker.java:176)
    at org.gradle.api.internal.tasks.testing.worker.TestWorker.executeAndMaintainThreadName(TestWorker.java:129)
    at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:100)
    at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:60)
    at org.gradle.process.internal.worker.child.ActionExecutionWorker.execute(ActionExecutionWorker.java:56)
    at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:133)
    at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:71)
    at worker.org.gradle.process.internal.worker.GradleWorkerMain.run(GradleWorkerMain.java:69)
    at worker.org.gradle.process.internal.worker.GradleWorkerMain.main(GradleWorkerMain.java:74)
Caused by: java.lang.ClassNotFoundException: androidx.test.internal.runner.junit4.AndroidJUnit4ClassRunner
    at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:581)
    at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
    at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522)
    at java.base/java.lang.Class.forName0(Native Method)
    at java.base/java.lang.Class.forName(Class.java:315)
    at androidx.test.ext.junit.runners.AndroidJUnit4.loadRunner(AndroidJUnit4.java:91)
    ... 36 more

My code is successfully finished up until the tests part. This is the code that I have written for tests:

package com.example.cupcake

import androidx.arch.core.executor.testing.InstantTaskExecutorRule
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.example.cupcake.model.OrderViewModel
import org.junit.Assert.assertEquals
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith

@RunWith(AndroidJUnit4::class)

class ViewModelTests2 {

    @get:Rule
    var instantTaskExecutorRule = InstantTaskExecutorRule()

    @Test
    fun quantity_twelve_cupcakes() {
        val viewModel = OrderViewModel()
        viewModel.quantity.observeForever {}
        viewModel.setQuantity(12)
        assertEquals(12, viewModel.quantity.value)
    }
    @Test
    fun price_twelve_cupcakes() {
        val viewModel = OrderViewModel()
        viewModel.setQuantity(12)
        viewModel.price.observeForever {}
        assertEquals("$27.00", viewModel.price.value)
    }

}

Do you see anything wrong in here?

tamarabuilds commented 2 years ago

Thanks for getting back to me. What are in your build.gradle files? Here's what I have:

build.gradle (Project: Cupcake)

// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
    ext.kotlin_version = "1.5.31"
    repositories {
        google()
        mavenCentral()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:7.0.3'
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"

        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

allprojects {
    repositories {
        google()
        mavenCentral()
    }
}

task clean(type: Delete) {
    delete rootProject.buildDir
}

build.gradle (Module: Cupcake.app)

plugins {
    id 'com.android.application'
    id 'kotlin-android'
    id 'kotlin-kapt'
}

android {
    compileSdkVersion 31

    defaultConfig {
        applicationId "com.example.cupcake"
        minSdkVersion 19
        targetSdkVersion 31
        versionCode 1
        versionName "1.0"
        vectorDrawables.useSupportLibrary = true
    }

    buildFeatures {
        dataBinding true
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }

    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }

    kotlinOptions {
        jvmTarget = '1.8'
    }
}

dependencies {
    def nav_version = "2.3.5"
    def lifecycle_version = "2.3.1"
    implementation 'androidx.appcompat:appcompat:1.3.1'
    implementation 'androidx.constraintlayout:constraintlayout:2.1.1'
    implementation 'androidx.core:core-ktx:1.6.0'
    implementation "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version"
    implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version"
    implementation "androidx.lifecycle:lifecycle-viewmodel-savedstate:$lifecycle_version"
    implementation "androidx.navigation:navigation-fragment-ktx:$nav_version"
    implementation "androidx.navigation:navigation-ui-ktx:$nav_version"
    implementation 'com.google.android.material:material:1.4.0'
    implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"

    testImplementation 'junit:junit:4.+'
    testImplementation 'androidx.arch.core:core-testing:2.1.0'
}