• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 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.functional.kotlinsrc.factory
18 
19 import com.google.common.truth.Truth.assertThat
20 import dagger.Component
21 import org.junit.Assert.fail
22 import org.junit.Test
23 import org.junit.runner.RunWith
24 import org.junit.runners.JUnit4
25 
26 /**
27  * Tests for factories for components with modules that do not require an instance to be passed to
28  * the factory. Includes both tests where the module does not have a corresponding parameter in the
29  * factory method and where it does have a parameter, for cases where that's allowed.
30  */
31 @RunWith(JUnit4::class)
32 class FactoryImplicitModulesTest {
33   @Component(modules = [AbstractModule::class])
34   internal interface AbstractModuleComponent {
stringnull35     fun string(): String
36 
37     @Component.Factory
38     interface Factory {
39       fun create(): AbstractModuleComponent
40     }
41   }
42 
43   @Test
abstractModulenull44   fun abstractModule() {
45     val component = DaggerFactoryImplicitModulesTest_AbstractModuleComponent.factory().create()
46     assertThat(component.string()).isEqualTo("foo")
47   }
48 
49   @Component(modules = [InstantiableConcreteModule::class])
50   internal interface InstantiableConcreteModuleComponent {
51     val int: Int
52 
53     @Component.Factory
54     interface Factory {
createnull55       fun create(): InstantiableConcreteModuleComponent
56     }
57   }
58 
59   @Test
60   fun instantiableConcreteModule() {
61     val component =
62       DaggerFactoryImplicitModulesTest_InstantiableConcreteModuleComponent.factory().create()
63     assertThat(component.int).isEqualTo(42)
64   }
65 
66   @Component(modules = [InstantiableConcreteModule::class])
67   internal interface InstantiableConcreteModuleWithFactoryParameterComponent {
68     val int: Int
69 
70     @Component.Factory
71     interface Factory {
createnull72       fun create(
73         module: InstantiableConcreteModule?
74       ): InstantiableConcreteModuleWithFactoryParameterComponent
75     }
76   }
77 
78   @Test
79   fun instantiableConcreteModule_withFactoryParameter() {
80     val component =
81       DaggerFactoryImplicitModulesTest_InstantiableConcreteModuleWithFactoryParameterComponent
82         .factory()
83         .create(InstantiableConcreteModule())
84     assertThat(component.int).isEqualTo(42)
85   }
86 
87   @Test
instantiableConcreteModule_withFactoryParameter_failsOnNullnull88   fun instantiableConcreteModule_withFactoryParameter_failsOnNull() {
89     try {
90       DaggerFactoryImplicitModulesTest_InstantiableConcreteModuleWithFactoryParameterComponent
91         .factory()
92         .create(null)
93       fail()
94     } catch (expected: NullPointerException) {}
95   }
96 
97   @Component(modules = [ConcreteModuleThatCouldBeAbstract::class])
98   internal interface ConcreteModuleThatCouldBeAbstractComponent {
99     val double: Double
100 
101     @Component.Factory
102     interface Factory {
createnull103       fun create(): ConcreteModuleThatCouldBeAbstractComponent
104     }
105   }
106 
107   @Test
108   fun concreteModuleThatCouldBeAbstract() {
109     val component =
110       DaggerFactoryImplicitModulesTest_ConcreteModuleThatCouldBeAbstractComponent.factory().create()
111     assertThat(component.double).isEqualTo(42.0)
112   }
113 
114   @Component(modules = [ConcreteModuleThatCouldBeAbstract::class])
115   internal interface ConcreteModuleThatCouldBeAbstractWithFactoryParameterComponent {
116     val double: Double
117 
118     @Component.Factory
119     interface Factory {
createnull120       fun create(
121         module: ConcreteModuleThatCouldBeAbstract?
122       ): ConcreteModuleThatCouldBeAbstractWithFactoryParameterComponent
123     }
124   }
125 
126   @Test
127   fun concreteModuleThatCouldBeAbstract_withFactoryParameter() {
128     val component: ConcreteModuleThatCouldBeAbstractWithFactoryParameterComponent =
129       DaggerFactoryImplicitModulesTest_ConcreteModuleThatCouldBeAbstractWithFactoryParameterComponent
130         .factory()
131         .create(ConcreteModuleThatCouldBeAbstract())
132     assertThat(component.double).isEqualTo(42.0)
133   }
134 
135   @Test
concreteModuleThatCouldBeAbstract_withFactoryParameter_failsOnNullnull136   fun concreteModuleThatCouldBeAbstract_withFactoryParameter_failsOnNull() {
137     // This matches what builders do when there's a setter for such a module; the setter checks that
138     // the argument is not null but otherwise ignores it.
139     // It's possible that we shouldn't even allow such a parameter for a factory, since unlike a
140     // builder, where the setter can just not be called, a factory doesn't give the option of not
141     // passing *something* for the unused parameter.
142     try {
143       DaggerFactoryImplicitModulesTest_ConcreteModuleThatCouldBeAbstractWithFactoryParameterComponent
144           .factory()
145           .create(null)
146       fail()
147     } catch (expected: NullPointerException) {}
148   }
149 }
150