Skip to content

Commit

Permalink
Add support for JUnit tests with Hilt Plugin
Browse files Browse the repository at this point in the history
Android transforms are not applied for JUnit tests which breaks when using
the Hilt Plugin and its transform. This CL adds a new custom test transform
task just for tests so that transformed classes are used in Android JUnit tests.

The task does not transform test sources, therefore temporarily allow specifying
a base class in @androidentrypoint that will be used even if the superclass
validation option is given to the processor. This helps us still have test-only
Android Entry Points.

Closes #1811

RELNOTES=n/a

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=309143731
  • Loading branch information
yigit authored and cpovirk committed Apr 30, 2020
1 parent 01ee5aa commit 9b48538
Show file tree
Hide file tree
Showing 44 changed files with 1,123 additions and 99 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,5 @@ gen-external-apklibs
/bazel-*

*.pyc

.gradle
16 changes: 11 additions & 5 deletions java/dagger/hilt/android/example/gradle/simple/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,7 @@
*/

apply plugin: 'com.android.application'
// TODO(bcorso): Reenable this plugin once it works with Robolectric tests.
// apply plugin: 'dagger.hilt.android.plugin'
apply plugin: 'dagger.hilt.android.plugin'

android {
compileSdkVersion 29
Expand All @@ -33,7 +32,13 @@ android {
sourceCompatibility 1.8
targetCompatibility 1.8
}
testOptions.unitTests.includeAndroidResources = true
testOptions {
unitTests.includeAndroidResources = true
}
}

hilt {
enableTransformForLocalTests = true
}

dependencies {
Expand All @@ -46,11 +51,12 @@ dependencies {

testImplementation 'com.google.truth:truth:1.0.1'
testImplementation 'junit:junit:4.13'
testImplementation 'org.robolectric:robolectric:4.3'
testImplementation 'org.robolectric:robolectric:4.3.1'
testImplementation 'androidx.core:core:1.2.0'
testImplementation 'androidx.test.ext:junit:1.1.1'
testImplementation 'androidx.test:runner:1.2.0'
// TODO(bcorso): This multidex dep shouldn't be required -- it's a dep for the generated code.
testImplementation 'androidx.multidex:multidex:2.0.0'
testImplementation 'androidx.multidex:multidex:2.0.1'
testImplementation 'com.google.dagger:hilt-android-testing:LOCAL-SNAPSHOT'
testAnnotationProcessor 'com.google.dagger:dagger-compiler:LOCAL-SNAPSHOT'
testAnnotationProcessor 'com.google.dagger:hilt-android-compiler:LOCAL-SNAPSHOT'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@
import javax.inject.Inject;

/** The settings activity of the application. */
@AndroidEntryPoint(AppCompatActivity.class)
public class SettingsActivity extends Hilt_SettingsActivity {
@AndroidEntryPoint
public class SettingsActivity extends AppCompatActivity {
private static final String TAG = SettingsActivity.class.getSimpleName();

@Inject SettingsGreeter greeter;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@
import javax.inject.Inject;

/** The main activity of the application. */
@AndroidEntryPoint(AppCompatActivity.class)
public class SimpleActivity extends Hilt_SimpleActivity {
@AndroidEntryPoint
public class SimpleActivity extends AppCompatActivity {
private static final String TAG = SimpleActivity.class.getSimpleName();

@Inject SimpleGreeter greeter;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@
* utilities in {@code Hilt} in Android.
*/
@GenerateComponents
@AndroidEntryPoint(Application.class)
public class SimpleApplication extends Hilt_SimpleApplication {
@AndroidEntryPoint
public class SimpleApplication extends Application {

// Shows that we can inject ApplicationComponent bindings into an application.
@Inject @Model String model;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ static String provideString() {
}

/** Test activity used to test activity injection */
// TODO(user): Update to extend non-gen code when test sources are also transformed.
@AndroidEntryPoint(AppCompatActivity.class)
public static final class TestActivity extends Hilt_Injection1Test_TestActivity {
@Inject @Named(ACTIVITY_QUALIFIER) String activityValue;
Expand All @@ -94,4 +95,14 @@ public void testActivityInjection() throws Exception {
scenario.onActivity(activity -> assertThat(activity.activityValue).isEqualTo(ACTIVITY_VALUE));
}
}

@Test
public void testSuperClassTransformation() {
try (ActivityScenario<TestActivity> scenario = ActivityScenario.launch(TestActivity.class)) {
scenario.onActivity(
activity ->
assertThat(activity.getClass().getSuperclass().getSimpleName())
.isEqualTo("Hilt_Injection1Test_TestActivity"));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ static String provideString() {
}

/** Test activity used to test activity injection */
// TODO(user): Update to extend non-gen code when test sources are also transformed.
@AndroidEntryPoint(AppCompatActivity.class)
public static final class TestActivity extends Hilt_Injection2Test_TestActivity {
@Inject @Named(ACTIVITY_QUALIFIER) String activityValue;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,4 +63,15 @@ public void testActivityInject() throws Exception {
.isEqualTo("ProdUser, you are on build FakeModel."));
}
}

@Test
public void testSuperClassTransformation() {
try (ActivityScenario<SettingsActivity> scenario =
ActivityScenario.launch(SettingsActivity.class)) {
scenario.onActivity(
activity ->
assertThat(activity.getClass().getSuperclass().getSimpleName())
.isEqualTo("Hilt_SettingsActivity"));
}
}
}
3 changes: 2 additions & 1 deletion java/dagger/hilt/android/example/gradle/simple/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,15 @@
buildscript {
ext {
kotlin_version = '1.3.61'
agp_version = System.getenv('AGP_VERSION') ?: "3.6.3"
}
repositories {
google()
jcenter()
mavenLocal()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.5.3'
classpath "com.android.tools.build:gradle:$agp_version"
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath 'com.google.dagger:hilt-android-gradle-plugin:LOCAL-SNAPSHOT'
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,7 @@
apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-kapt'
// TODO(bcorso): Reenable this plugin once it works with Robolectric tests.
// apply plugin: 'dagger.hilt.android.plugin'
apply plugin: 'dagger.hilt.android.plugin'

android {
compileSdkVersion 29
Expand All @@ -39,6 +38,10 @@ kapt {
correctErrorTypes true
}

hilt {
enableTransformForLocalTests = true
}

dependencies {
// This is api instead of implementation since Kotlin modules here consumed
// by the app need to expose @kotlin.Metadata
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ import androidx.appcompat.app.AppCompatActivity
import dagger.hilt.android.AndroidEntryPoint
import javax.inject.Inject

@AndroidEntryPoint(AppCompatActivity::class)
class FeatureActivity : Hilt_FeatureActivity() {
@AndroidEntryPoint
class FeatureActivity : AppCompatActivity() {
@Inject lateinit var counter: FeatureCounter

override fun onCreate(savedInstanceState: Bundle?) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
android.useAndroidX=true
android.enableJetifier=true
android.enableUnitTestBinaryResources=true
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-6.3-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
18 changes: 18 additions & 0 deletions java/dagger/hilt/android/example/gradle/simpleKotlin/BUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Copyright (C) 2020 The Dagger Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# Description:
# A skeletal Kotlin application that demonstrates wiring for an injected Application and Activity.

package(default_visibility = ["//:src"])
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/*
* Copyright (C) 2020 The Dagger Authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'dagger.hilt.android.plugin'
apply plugin: 'kotlin-kapt'

android {
compileSdkVersion 29
buildToolsVersion "29.0.3"

defaultConfig {
applicationId "dagger.hilt.android.example.gradle.simpleKotlin"
minSdkVersion 21
targetSdkVersion 29
versionCode 1
versionName "1.0"
}
compileOptions {
sourceCompatibility 1.8
targetCompatibility 1.8
}
testOptions {
unitTests.includeAndroidResources = true
}
}

hilt {
enableTransformForLocalTests = true
}

dependencies {
implementation fileTree(dir: "libs", include: ["*.jar"])
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation 'androidx.appcompat:appcompat:1.1.0'

implementation 'com.google.dagger:dagger:LOCAL-SNAPSHOT'
kapt 'com.google.dagger:dagger-compiler:LOCAL-SNAPSHOT'
implementation 'com.google.dagger:hilt-android:LOCAL-SNAPSHOT'
kapt 'com.google.dagger:hilt-android-compiler:LOCAL-SNAPSHOT'

testImplementation 'com.google.truth:truth:1.0.1'
testImplementation 'junit:junit:4.13'
testImplementation 'org.robolectric:robolectric:4.3.1'
testImplementation 'androidx.core:core:1.1.0'
// TODO(bcorso): This multidex dep shouldn't be required -- it's a dep for the generated code.
testImplementation 'androidx.multidex:multidex:2.0.0'
testImplementation 'com.google.dagger:hilt-android-testing:LOCAL-SNAPSHOT'
kaptTest 'com.google.dagger:dagger-compiler:LOCAL-SNAPSHOT'
kaptTest 'com.google.dagger:hilt-android-compiler:LOCAL-SNAPSHOT'
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright (C) 2020 The Dagger Authors.
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="dagger.hilt.android.example.gradle.simpleKotlin">

<application
android:name=".KotlinApplication"
android:allowBackup="true"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/Theme.AppCompat.Light">
<activity android:name=".MainActivity" android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* Copyright (C) 2020 The Dagger Authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package dagger.hilt.android.example.gradle.simpleKotlin

import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.android.components.ActivityComponent

@Module
@InstallIn(ActivityComponent::class)
object ActivityModule {
@UserName
@Provides
fun provideUserName(): String {
return "Android User"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* Copyright (C) 2020 The Dagger Authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package dagger.hilt.android.example.gradle.simpleKotlin

import android.os.Build
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.android.components.ApplicationComponent

@Module
@InstallIn(ApplicationComponent::class)
object ApplicationModule {
@Provides
@Model
fun provideModel(): String {
return Build.MODEL
}
}
Loading

0 comments on commit 9b48538

Please sign in to comment.