1 /* 2 * Copyright (C) 2020 The Dagger Authors. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package dagger.hilt.android.processor.internal.viewmodel 18 19 import com.google.testing.compile.CompilationSubject.assertThat 20 import com.google.testing.compile.Compiler 21 import org.junit.Test 22 import org.junit.runner.RunWith 23 import org.junit.runners.JUnit4 24 25 @RunWith(JUnit4::class) 26 class ViewModelGeneratorTest { 27 compilernull28 private fun compiler(): Compiler = Compiler.javac().withProcessors(ViewModelProcessor()) 29 30 @Test 31 fun verifyModule_noArg() { 32 val myViewModel = """ 33 package dagger.hilt.android.test; 34 35 import dagger.hilt.android.lifecycle.HiltViewModel; 36 import androidx.lifecycle.ViewModel; 37 import javax.inject.Inject; 38 39 @HiltViewModel 40 class MyViewModel extends ViewModel { 41 @Inject 42 MyViewModel() { } 43 } 44 """.toJFO("dagger.hilt.android.test.MyViewModel") 45 46 val expected = """ 47 package dagger.hilt.android.test; 48 49 $GENERATED_ANNOTATION 50 @OriginatingElement( 51 topLevelClass = MyViewModel.class 52 ) 53 public final class MyViewModel_HiltModules { 54 private MyViewModel_HiltModules() { 55 } 56 57 @Module 58 @InstallIn(ViewModelComponent.class) 59 public static abstract class BindsModule { 60 private BindsModule() {} 61 62 @Binds 63 @IntoMap 64 @StringKey("dagger.hilt.android.test.MyViewModel") 65 @HiltViewModelMap 66 public abstract ViewModel binds(MyViewModel vm); 67 } 68 69 @Module 70 @InstallIn(ActivityRetainedComponent.class) 71 public static final class KeyModule { 72 private KeyModule() { 73 } 74 75 @Provides 76 @IntoSet 77 @HiltViewModelMap.KeySet 78 public static String provide() { 79 return "dagger.hilt.android.test.MyViewModel"; 80 } 81 } 82 } 83 """.toJFO("dagger.hilt.android.test.MyViewModel_HiltModule") 84 85 val compilation = compiler() 86 .compile(myViewModel) 87 assertThat(compilation).apply { 88 succeeded() 89 generatedSourceFile("dagger.hilt.android.test.MyViewModel_HiltModules") 90 .containsElementsIn(expected) 91 } 92 } 93 94 @Test verifyModule_savedStateOnlyArgnull95 fun verifyModule_savedStateOnlyArg() { 96 val myViewModel = """ 97 package dagger.hilt.android.test; 98 99 import dagger.hilt.android.lifecycle.HiltViewModel; 100 import androidx.lifecycle.ViewModel; 101 import androidx.lifecycle.SavedStateHandle; 102 import javax.inject.Inject; 103 104 @HiltViewModel 105 class MyViewModel extends ViewModel { 106 @Inject 107 MyViewModel(SavedStateHandle savedState) { } 108 } 109 """.toJFO("dagger.hilt.android.test.MyViewModel") 110 111 val expected = """ 112 package dagger.hilt.android.test; 113 114 $GENERATED_ANNOTATION 115 @OriginatingElement( 116 topLevelClass = MyViewModel.class 117 ) 118 public final class MyViewModel_HiltModules { 119 private MyViewModel_HiltModules() { 120 } 121 122 @Module 123 @InstallIn(ViewModelComponent.class) 124 public static abstract class BindsModule { 125 private BindsModule() {} 126 127 @Binds 128 @IntoMap 129 @StringKey("dagger.hilt.android.test.MyViewModel") 130 @HiltViewModelMap 131 public abstract ViewModel binds(MyViewModel vm); 132 } 133 134 @Module 135 @InstallIn(ActivityRetainedComponent.class) 136 public static final class KeyModule { 137 private KeyModule() { 138 } 139 140 @Provides 141 @IntoSet 142 @HiltViewModelMap.KeySet 143 public static String provide() { 144 return "dagger.hilt.android.test.MyViewModel"; 145 } 146 } 147 } 148 """.toJFO("dagger.hilt.android.test.MyViewModel_HiltModule") 149 150 val compilation = compiler() 151 .compile(myViewModel) 152 assertThat(compilation).apply { 153 succeeded() 154 generatedSourceFile("dagger.hilt.android.test.MyViewModel_HiltModules") 155 .containsElementsIn(expected) 156 } 157 } 158 159 @Test verifyModule_mixedArgsnull160 fun verifyModule_mixedArgs() { 161 val foo = """ 162 package dagger.hilt.android.test; 163 164 public class Foo { } 165 """.toJFO("dagger.hilt.android.test.Foo") 166 167 val myViewModel = """ 168 package dagger.hilt.android.test; 169 170 import dagger.hilt.android.lifecycle.HiltViewModel; 171 import androidx.lifecycle.ViewModel; 172 import androidx.lifecycle.SavedStateHandle; 173 import java.lang.String; 174 import javax.inject.Inject; 175 176 @HiltViewModel 177 class MyViewModel extends ViewModel { 178 @Inject 179 MyViewModel(String s, Foo f, SavedStateHandle savedState, long l) { } 180 } 181 """.toJFO("dagger.hilt.android.test.MyViewModel") 182 183 val expected = """ 184 package dagger.hilt.android.test; 185 186 $GENERATED_ANNOTATION 187 @OriginatingElement( 188 topLevelClass = MyViewModel.class 189 ) 190 public final class MyViewModel_HiltModules { 191 private MyViewModel_HiltModules() { 192 } 193 194 @Module 195 @InstallIn(ViewModelComponent.class) 196 public static abstract class BindsModule { 197 private BindsModule() {} 198 199 @Binds 200 @IntoMap 201 @StringKey("dagger.hilt.android.test.MyViewModel") 202 @HiltViewModelMap 203 public abstract ViewModel binds(MyViewModel vm); 204 } 205 206 @Module 207 @InstallIn(ActivityRetainedComponent.class) 208 public static final class KeyModule { 209 private KeyModule() { 210 } 211 212 @Provides 213 @IntoSet 214 @HiltViewModelMap.KeySet 215 public static String provide() { 216 return "dagger.hilt.android.test.MyViewModel"; 217 } 218 } 219 } 220 """.toJFO("dagger.hilt.android.test.MyViewModel_HiltModule") 221 222 val compilation = compiler() 223 .compile(foo, myViewModel) 224 assertThat(compilation).apply { 225 succeeded() 226 generatedSourceFile("dagger.hilt.android.test.MyViewModel_HiltModules") 227 .containsElementsIn(expected) 228 } 229 } 230 231 @Test verifyModule_mixedAndProviderArgsnull232 fun verifyModule_mixedAndProviderArgs() { 233 val foo = """ 234 package dagger.hilt.android.test; 235 236 public class Foo { } 237 """.toJFO("dagger.hilt.android.test.Foo") 238 239 val myViewModel = """ 240 package dagger.hilt.android.test; 241 242 import dagger.hilt.android.lifecycle.HiltViewModel; 243 import androidx.lifecycle.ViewModel; 244 import androidx.lifecycle.SavedStateHandle; 245 import java.lang.String; 246 import javax.inject.Inject; 247 import javax.inject.Provider; 248 249 @HiltViewModel 250 class MyViewModel extends ViewModel { 251 @Inject 252 MyViewModel(String s, Provider<Foo> f, SavedStateHandle savedState) { } 253 } 254 """.toJFO("dagger.hilt.android.test.MyViewModel") 255 256 val expected = """ 257 package dagger.hilt.android.test; 258 259 $GENERATED_ANNOTATION 260 @OriginatingElement( 261 topLevelClass = MyViewModel.class 262 ) 263 public final class MyViewModel_HiltModules { 264 private MyViewModel_HiltModules() { 265 } 266 267 @Module 268 @InstallIn(ViewModelComponent.class) 269 public static abstract class BindsModule { 270 private BindsModule() {} 271 272 @Binds 273 @IntoMap 274 @StringKey("dagger.hilt.android.test.MyViewModel") 275 @HiltViewModelMap 276 public abstract ViewModel binds(MyViewModel vm); 277 } 278 279 @Module 280 @InstallIn(ActivityRetainedComponent.class) 281 public static final class KeyModule { 282 private KeyModule() { 283 } 284 285 @Provides 286 @IntoSet 287 @HiltViewModelMap.KeySet 288 public static String provide() { 289 return "dagger.hilt.android.test.MyViewModel"; 290 } 291 } 292 } 293 """.toJFO("dagger.hilt.android.test.MyViewModel_HiltModules") 294 295 val compilation = compiler() 296 .compile(foo, myViewModel) 297 assertThat(compilation).apply { 298 succeeded() 299 generatedSourceFile("dagger.hilt.android.test.MyViewModel_HiltModules") 300 .containsElementsIn(expected) 301 } 302 } 303 304 @Test verifyModule_qualifiedArgsnull305 fun verifyModule_qualifiedArgs() { 306 val myQualifier = """ 307 package dagger.hilt.android.test; 308 309 import javax.inject.Qualifier; 310 311 @Qualifier 312 public @interface MyQualifier { } 313 """.toJFO("dagger.hilt.android.test.MyQualifier") 314 315 val myViewModel = """ 316 package dagger.hilt.android.test; 317 318 import dagger.hilt.android.lifecycle.HiltViewModel; 319 import androidx.lifecycle.ViewModel; 320 import androidx.lifecycle.SavedStateHandle; 321 import java.lang.Long; 322 import java.lang.String; 323 import javax.inject.Inject; 324 import javax.inject.Named; 325 import javax.inject.Provider; 326 327 @HiltViewModel 328 class MyViewModel extends ViewModel { 329 @Inject 330 MyViewModel(@Named("TheString") String s, @MyQualifier Provider<Long> l, 331 SavedStateHandle savedState) { 332 } 333 } 334 """.toJFO("dagger.hilt.android.test.MyViewModel") 335 336 val expected = """ 337 package dagger.hilt.android.test; 338 339 $GENERATED_ANNOTATION 340 @OriginatingElement( 341 topLevelClass = MyViewModel.class 342 ) 343 public final class MyViewModel_HiltModules { 344 private MyViewModel_HiltModules() { 345 } 346 347 @Module 348 @InstallIn(ViewModelComponent.class) 349 public static abstract class BindsModule { 350 private BindsModule() {} 351 352 @Binds 353 @IntoMap 354 @StringKey("dagger.hilt.android.test.MyViewModel") 355 @HiltViewModelMap 356 public abstract ViewModel binds(MyViewModel vm); 357 } 358 359 @Module 360 @InstallIn(ActivityRetainedComponent.class) 361 public static final class KeyModule { 362 private KeyModule() { 363 } 364 365 @Provides 366 @IntoSet 367 @HiltViewModelMap.KeySet 368 public static String provide() { 369 return "dagger.hilt.android.test.MyViewModel"; 370 } 371 } 372 } 373 """.toJFO("dagger.hilt.android.test.MyViewModel_HiltModules") 374 375 val compilation = compiler() 376 .compile(myQualifier, myViewModel) 377 assertThat(compilation).apply { 378 succeeded() 379 generatedSourceFile("dagger.hilt.android.test.MyViewModel_HiltModules") 380 .containsElementsIn(expected) 381 } 382 } 383 384 @Test verifyInnerClassnull385 fun verifyInnerClass() { 386 val viewModel = """ 387 package dagger.hilt.android.test; 388 389 import dagger.hilt.android.lifecycle.HiltViewModel; 390 import androidx.lifecycle.ViewModel; 391 import javax.inject.Inject; 392 393 class Outer { 394 @HiltViewModel 395 static class InnerViewModel extends ViewModel { 396 @Inject 397 InnerViewModel() { } 398 } 399 } 400 """.toJFO("dagger.hilt.android.test.Outer") 401 402 val expectedModule = """ 403 package dagger.hilt.android.test; 404 405 $GENERATED_ANNOTATION 406 @OriginatingElement( 407 topLevelClass = Outer.class 408 ) 409 public final class Outer_InnerViewModel_HiltModules { 410 private Outer_InnerViewModel_HiltModules() { 411 } 412 413 @Module 414 @InstallIn(ViewModelComponent.class) 415 public static abstract class BindsModule { 416 private BindsModule() {} 417 418 @Binds 419 @IntoMap 420 @StringKey("dagger.hilt.android.test.Outer${'$'}InnerViewModel") 421 @HiltViewModelMap 422 public abstract ViewModel binds(Outer.InnerViewModel vm); 423 } 424 425 @Module 426 @InstallIn(ActivityRetainedComponent.class) 427 public static final class KeyModule { 428 private KeyModule() { 429 } 430 431 @Provides 432 @IntoSet 433 @HiltViewModelMap.KeySet 434 public static String provide() { 435 return "dagger.hilt.android.test.Outer${'$'}InnerViewModel"; 436 } 437 } 438 } 439 """.toJFO("dagger.hilt.android.test.Outer_InnerViewModel_HiltModules") 440 441 val compilation = compiler() 442 .compile(viewModel) 443 assertThat(compilation).apply { 444 succeeded() 445 generatedSourceFile("dagger.hilt.android.test.Outer_InnerViewModel_HiltModules") 446 .containsElementsIn(expectedModule) 447 } 448 } 449 } 450