1*f585d8a3SJacky Wang /* 2*f585d8a3SJacky Wang * Copyright (C) 2023 The Dagger Authors. 3*f585d8a3SJacky Wang * 4*f585d8a3SJacky Wang * Licensed under the Apache License, Version 2.0 (the "License"); 5*f585d8a3SJacky Wang * you may not use this file except in compliance with the License. 6*f585d8a3SJacky Wang * You may obtain a copy of the License at 7*f585d8a3SJacky Wang * 8*f585d8a3SJacky Wang * http://www.apache.org/licenses/LICENSE-2.0 9*f585d8a3SJacky Wang * 10*f585d8a3SJacky Wang * Unless required by applicable law or agreed to in writing, software 11*f585d8a3SJacky Wang * distributed under the License is distributed on an "AS IS" BASIS, 12*f585d8a3SJacky Wang * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*f585d8a3SJacky Wang * See the License for the specific language governing permissions and 14*f585d8a3SJacky Wang * limitations under the License. 15*f585d8a3SJacky Wang */ 16*f585d8a3SJacky Wang 17*f585d8a3SJacky Wang package dagger.functional.nullables; 18*f585d8a3SJacky Wang 19*f585d8a3SJacky Wang import static com.google.common.truth.Truth.assertThat; 20*f585d8a3SJacky Wang import static org.junit.Assert.assertThrows; 21*f585d8a3SJacky Wang 22*f585d8a3SJacky Wang import dagger.Component; 23*f585d8a3SJacky Wang import dagger.Module; 24*f585d8a3SJacky Wang import dagger.Provides; 25*f585d8a3SJacky Wang import javax.inject.Provider; 26*f585d8a3SJacky Wang import org.jspecify.annotations.Nullable; 27*f585d8a3SJacky Wang import org.junit.Test; 28*f585d8a3SJacky Wang import org.junit.runner.RunWith; 29*f585d8a3SJacky Wang import org.junit.runners.JUnit4; 30*f585d8a3SJacky Wang 31*f585d8a3SJacky Wang @RunWith(JUnit4.class) 32*f585d8a3SJacky Wang public final class JspecifyNullableTest { 33*f585d8a3SJacky Wang @Component(modules = MyModule.class, dependencies = ComponentDependency.class) 34*f585d8a3SJacky Wang interface MyComponent { getInt()35*f585d8a3SJacky Wang Integer getInt(); getInnerType()36*f585d8a3SJacky Wang InnerType getInnerType(); getDependencyProvider()37*f585d8a3SJacky Wang Provider<Dependency> getDependencyProvider(); 38*f585d8a3SJacky Wang } 39*f585d8a3SJacky Wang 40*f585d8a3SJacky Wang interface Dependency {} 41*f585d8a3SJacky Wang 42*f585d8a3SJacky Wang interface InnerType {} 43*f585d8a3SJacky Wang 44*f585d8a3SJacky Wang @Module 45*f585d8a3SJacky Wang static class MyModule { 46*f585d8a3SJacky Wang private final Integer integer; 47*f585d8a3SJacky Wang private final InnerType innerType; 48*f585d8a3SJacky Wang MyModule(Integer integer, InnerType innerType)49*f585d8a3SJacky Wang MyModule(Integer integer, InnerType innerType) { 50*f585d8a3SJacky Wang this.integer = integer; 51*f585d8a3SJacky Wang this.innerType = innerType; 52*f585d8a3SJacky Wang } 53*f585d8a3SJacky Wang 54*f585d8a3SJacky Wang @Provides provideInt()55*f585d8a3SJacky Wang @Nullable Integer provideInt() { 56*f585d8a3SJacky Wang return integer; 57*f585d8a3SJacky Wang } 58*f585d8a3SJacky Wang 59*f585d8a3SJacky Wang @Provides provideInnerType()60*f585d8a3SJacky Wang @Nullable InnerType provideInnerType() { 61*f585d8a3SJacky Wang return innerType; 62*f585d8a3SJacky Wang } 63*f585d8a3SJacky Wang } 64*f585d8a3SJacky Wang 65*f585d8a3SJacky Wang @Component(modules = DependencyModule.class) 66*f585d8a3SJacky Wang interface ComponentDependency { dependency()67*f585d8a3SJacky Wang @Nullable Dependency dependency(); 68*f585d8a3SJacky Wang } 69*f585d8a3SJacky Wang 70*f585d8a3SJacky Wang @Module 71*f585d8a3SJacky Wang static class DependencyModule { 72*f585d8a3SJacky Wang private final Dependency dependency; 73*f585d8a3SJacky Wang DependencyModule(Dependency dependency)74*f585d8a3SJacky Wang DependencyModule(Dependency dependency) { 75*f585d8a3SJacky Wang this.dependency = dependency; 76*f585d8a3SJacky Wang } 77*f585d8a3SJacky Wang 78*f585d8a3SJacky Wang @Provides provideDependency()79*f585d8a3SJacky Wang @Nullable Dependency provideDependency() { 80*f585d8a3SJacky Wang return dependency; 81*f585d8a3SJacky Wang } 82*f585d8a3SJacky Wang } 83*f585d8a3SJacky Wang 84*f585d8a3SJacky Wang @Test testWithValue()85*f585d8a3SJacky Wang public void testWithValue() { 86*f585d8a3SJacky Wang MyComponent component = DaggerJspecifyNullableTest_MyComponent.builder() 87*f585d8a3SJacky Wang .myModule(new MyModule(15, new InnerType() {})) 88*f585d8a3SJacky Wang .componentDependency( 89*f585d8a3SJacky Wang DaggerJspecifyNullableTest_ComponentDependency.builder() 90*f585d8a3SJacky Wang .dependencyModule(new DependencyModule(new Dependency() {})).build()) 91*f585d8a3SJacky Wang .build(); 92*f585d8a3SJacky Wang assertThat(component.getInt()).isEqualTo(15); 93*f585d8a3SJacky Wang assertThat(component.getInnerType()).isNotNull(); 94*f585d8a3SJacky Wang assertThat(component.getDependencyProvider().get()).isNotNull(); 95*f585d8a3SJacky Wang } 96*f585d8a3SJacky Wang 97*f585d8a3SJacky Wang @Test testWithNull()98*f585d8a3SJacky Wang public void testWithNull() { 99*f585d8a3SJacky Wang MyComponent component = DaggerJspecifyNullableTest_MyComponent.builder() 100*f585d8a3SJacky Wang .myModule(new MyModule(null, null)) 101*f585d8a3SJacky Wang .componentDependency( 102*f585d8a3SJacky Wang DaggerJspecifyNullableTest_ComponentDependency.builder() 103*f585d8a3SJacky Wang .dependencyModule(new DependencyModule(null)).build()) 104*f585d8a3SJacky Wang .build(); 105*f585d8a3SJacky Wang NullPointerException expectedException = 106*f585d8a3SJacky Wang assertThrows(NullPointerException.class, component::getInt); 107*f585d8a3SJacky Wang assertThat(expectedException) 108*f585d8a3SJacky Wang .hasMessageThat() 109*f585d8a3SJacky Wang .contains("Cannot return null from a non-@Nullable @Provides method"); 110*f585d8a3SJacky Wang NullPointerException expectedException2 = 111*f585d8a3SJacky Wang assertThrows(NullPointerException.class, component::getInnerType); 112*f585d8a3SJacky Wang assertThat(expectedException2) 113*f585d8a3SJacky Wang .hasMessageThat() 114*f585d8a3SJacky Wang .contains("Cannot return null from a non-@Nullable @Provides method"); 115*f585d8a3SJacky Wang NullPointerException expectedException3 = 116*f585d8a3SJacky Wang assertThrows(NullPointerException.class, () -> component.getDependencyProvider().get()); 117*f585d8a3SJacky Wang assertThat(expectedException3) 118*f585d8a3SJacky Wang .hasMessageThat() 119*f585d8a3SJacky Wang .contains("Cannot return null from a non-@Nullable @Provides method"); 120*f585d8a3SJacky Wang } 121*f585d8a3SJacky Wang } 122