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