1 /* 2 * Copyright (C) 2015 Google, Inc. 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 package dagger.internal.codegen; 17 18 import com.google.common.collect.ImmutableList; 19 import com.google.testing.compile.JavaFileObjects; 20 import javax.tools.JavaFileObject; 21 import org.junit.Test; 22 import org.junit.runner.RunWith; 23 import org.junit.runners.JUnit4; 24 25 import static com.google.common.truth.Truth.assertAbout; 26 import static com.google.testing.compile.JavaSourcesSubjectFactory.javaSources; 27 28 @RunWith(JUnit4.class) 29 public class MissingBindingSuggestionsTest { 30 private static JavaFileObject injectable(String className, String constructorParams) { 31 return JavaFileObjects.forSourceLines("test." + className, 32 "package test;", 33 "", 34 "import javax.inject.Inject;", 35 "", 36 "class " + className +" {", 37 " @Inject " + className + "(" + constructorParams + ") {}", 38 "}"); 39 } 40 41 private static JavaFileObject emptyInterface(String interfaceName) { 42 return JavaFileObjects.forSourceLines("test." + interfaceName, 43 "package test;", 44 "", 45 "import javax.inject.Inject;", 46 "", 47 "interface " + interfaceName +" {}"); 48 } 49 50 @Test public void suggestsBindingInSeparateComponent() { 51 JavaFileObject fooComponent = JavaFileObjects.forSourceLines("test.FooComponent", 52 "package test;", 53 "", 54 "import dagger.Subcomponent;", 55 "", 56 "@Subcomponent", 57 "interface FooComponent {", 58 " Foo getFoo();", 59 "}"); 60 JavaFileObject barModule = JavaFileObjects.forSourceLines("test.BarModule", 61 "package test;", 62 "", 63 "import dagger.Provides;", 64 "import javax.inject.Inject;", 65 "", 66 "@dagger.Module", 67 "final class BarModule {", 68 " @Provides Bar provideBar() {return null;}", 69 "}"); 70 JavaFileObject barComponent = JavaFileObjects.forSourceLines("test.BarComponent", 71 "package test;", 72 "", 73 "import dagger.Subcomponent;", 74 "", 75 "@Subcomponent(modules = {BarModule.class})", 76 "interface BarComponent {", 77 " Bar getBar();", 78 "}"); 79 JavaFileObject foo = injectable("Foo", "Bar bar"); 80 JavaFileObject bar = emptyInterface("Bar"); 81 82 JavaFileObject topComponent = JavaFileObjects.forSourceLines("test.TopComponent", 83 "package test;", 84 "", 85 "import dagger.Component;", 86 "", 87 "@Component", 88 "interface TopComponent {", 89 " FooComponent getFoo();", 90 " BarComponent getBar(BarModule barModule);", 91 "}"); 92 93 assertAbout(javaSources()) 94 .that(ImmutableList.of( 95 fooComponent, barComponent, topComponent, foo, bar, barModule)) 96 .processedWith(new ComponentProcessor()) 97 .failsToCompile() 98 .withErrorContaining("A binding with matching key exists in component: test.BarComponent"); 99 } 100 101 @Test public void suggestsBindingInNestedSubcomponent() { 102 JavaFileObject fooComponent = JavaFileObjects.forSourceLines("test.FooComponent", 103 "package test;", 104 "", 105 "import dagger.Subcomponent;", 106 "", 107 "@Subcomponent", 108 "interface FooComponent {", 109 " Foo getFoo();", 110 "}"); 111 JavaFileObject barComponent = JavaFileObjects.forSourceLines("test.BarComponent", 112 "package test;", 113 "", 114 "import dagger.Subcomponent;", 115 "", 116 "@Subcomponent()", 117 "interface BarComponent {", 118 " BazComponent getBaz();", 119 "}"); 120 JavaFileObject bazModule = JavaFileObjects.forSourceLines("test.BazModule", 121 "package test;", 122 "", 123 "import dagger.Provides;", 124 "import javax.inject.Inject;", 125 "", 126 "@dagger.Module", 127 "final class BazModule {", 128 " @Provides Baz provideBaz() {return null;}", 129 "}"); 130 JavaFileObject bazComponent = JavaFileObjects.forSourceLines("test.BazComponent", 131 "package test;", 132 "", 133 "import dagger.Subcomponent;", 134 "", 135 "@Subcomponent(modules = {BazModule.class})", 136 "interface BazComponent {", 137 " Baz getBaz();", 138 "}"); 139 JavaFileObject foo = injectable("Foo", "Baz baz"); 140 JavaFileObject baz = emptyInterface("Baz"); 141 142 JavaFileObject topComponent = JavaFileObjects.forSourceLines("test.TopComponent", 143 "package test;", 144 "", 145 "import dagger.Component;", 146 "", 147 "@Component", 148 "interface TopComponent {", 149 " FooComponent getFoo();", 150 " BarComponent getBar();", 151 "}"); 152 153 assertAbout(javaSources()) 154 .that(ImmutableList.of( 155 fooComponent, barComponent, bazComponent, topComponent, foo, baz, bazModule)) 156 .processedWith(new ComponentProcessor()) 157 .failsToCompile() 158 .withErrorContaining("A binding with matching key exists in component: test.BazComponent"); 159 } 160 } 161