1 /* 2 * Copyright (C) 2023 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.nullables; 18 19 import static com.google.common.truth.Truth.assertThat; 20 import static org.junit.Assert.assertThrows; 21 22 import dagger.Component; 23 import dagger.Module; 24 import dagger.Provides; 25 import javax.inject.Provider; 26 import org.jspecify.annotations.Nullable; 27 import org.junit.Test; 28 import org.junit.runner.RunWith; 29 import org.junit.runners.JUnit4; 30 31 @RunWith(JUnit4.class) 32 public final class JspecifyNullableTest { 33 @Component(modules = MyModule.class, dependencies = ComponentDependency.class) 34 interface MyComponent { getInt()35 Integer getInt(); getInnerType()36 InnerType getInnerType(); getDependencyProvider()37 Provider<Dependency> getDependencyProvider(); 38 } 39 40 interface Dependency {} 41 42 interface InnerType {} 43 44 @Module 45 static class MyModule { 46 private final Integer integer; 47 private final InnerType innerType; 48 MyModule(Integer integer, InnerType innerType)49 MyModule(Integer integer, InnerType innerType) { 50 this.integer = integer; 51 this.innerType = innerType; 52 } 53 54 @Provides provideInt()55 @Nullable Integer provideInt() { 56 return integer; 57 } 58 59 @Provides provideInnerType()60 @Nullable InnerType provideInnerType() { 61 return innerType; 62 } 63 } 64 65 @Component(modules = DependencyModule.class) 66 interface ComponentDependency { dependency()67 @Nullable Dependency dependency(); 68 } 69 70 @Module 71 static class DependencyModule { 72 private final Dependency dependency; 73 DependencyModule(Dependency dependency)74 DependencyModule(Dependency dependency) { 75 this.dependency = dependency; 76 } 77 78 @Provides provideDependency()79 @Nullable Dependency provideDependency() { 80 return dependency; 81 } 82 } 83 84 @Test testWithValue()85 public void testWithValue() { 86 MyComponent component = DaggerJspecifyNullableTest_MyComponent.builder() 87 .myModule(new MyModule(15, new InnerType() {})) 88 .componentDependency( 89 DaggerJspecifyNullableTest_ComponentDependency.builder() 90 .dependencyModule(new DependencyModule(new Dependency() {})).build()) 91 .build(); 92 assertThat(component.getInt()).isEqualTo(15); 93 assertThat(component.getInnerType()).isNotNull(); 94 assertThat(component.getDependencyProvider().get()).isNotNull(); 95 } 96 97 @Test testWithNull()98 public void testWithNull() { 99 MyComponent component = DaggerJspecifyNullableTest_MyComponent.builder() 100 .myModule(new MyModule(null, null)) 101 .componentDependency( 102 DaggerJspecifyNullableTest_ComponentDependency.builder() 103 .dependencyModule(new DependencyModule(null)).build()) 104 .build(); 105 NullPointerException expectedException = 106 assertThrows(NullPointerException.class, component::getInt); 107 assertThat(expectedException) 108 .hasMessageThat() 109 .contains("Cannot return null from a non-@Nullable @Provides method"); 110 NullPointerException expectedException2 = 111 assertThrows(NullPointerException.class, component::getInnerType); 112 assertThat(expectedException2) 113 .hasMessageThat() 114 .contains("Cannot return null from a non-@Nullable @Provides method"); 115 NullPointerException expectedException3 = 116 assertThrows(NullPointerException.class, () -> component.getDependencyProvider().get()); 117 assertThat(expectedException3) 118 .hasMessageThat() 119 .contains("Cannot return null from a non-@Nullable @Provides method"); 120 } 121 } 122