• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.JavaSourceSubjectFactory.javaSource;
27 import static com.google.testing.compile.JavaSourcesSubjectFactory.javaSources;
28 
29 /** Tests for {@link dagger.Subcomponent.Builder} validation. */
30 @RunWith(JUnit4.class)
31 public class SubcomponentBuilderValidationTest {
32 
33   private static final ErrorMessages.SubcomponentBuilderMessages MSGS =
34       new ErrorMessages.SubcomponentBuilderMessages();
35 
36   @Test
testRefSubcomponentAndSubBuilderFails()37   public void testRefSubcomponentAndSubBuilderFails() {
38     JavaFileObject componentFile = JavaFileObjects.forSourceLines("test.ParentComponent",
39         "package test;",
40         "",
41         "import dagger.Component;",
42         "",
43         "import javax.inject.Provider;",
44         "",
45         "@Component",
46         "interface ParentComponent {",
47         "  ChildComponent child();",
48         "  ChildComponent.Builder builder();",
49         "}");
50     JavaFileObject childComponentFile = JavaFileObjects.forSourceLines("test.ChildComponent",
51         "package test;",
52         "",
53         "import dagger.Subcomponent;",
54         "",
55         "@Subcomponent",
56         "interface ChildComponent {",
57         "  @Subcomponent.Builder",
58         "  static interface Builder {",
59         "    ChildComponent build();",
60         "  }",
61         "}");
62     assertAbout(javaSources()).that(ImmutableList.of(componentFile, childComponentFile))
63         .processedWith(new ComponentProcessor())
64         .failsToCompile()
65         .withErrorContaining(String.format(MSGS.moreThanOneRefToSubcomponent(),
66             "test.ChildComponent", "[child(), builder()]"))
67         .in(componentFile);
68   }
69 
70   @Test
testRefSubBuilderTwiceFails()71   public void testRefSubBuilderTwiceFails() {
72     JavaFileObject componentFile = JavaFileObjects.forSourceLines("test.ParentComponent",
73         "package test;",
74         "",
75         "import dagger.Component;",
76         "",
77         "import javax.inject.Provider;",
78         "",
79         "@Component",
80         "interface ParentComponent {",
81         "  ChildComponent.Builder builder1();",
82         "  ChildComponent.Builder builder2();",
83         "}");
84     JavaFileObject childComponentFile = JavaFileObjects.forSourceLines("test.ChildComponent",
85         "package test;",
86         "",
87         "import dagger.Subcomponent;",
88         "",
89         "@Subcomponent",
90         "interface ChildComponent {",
91         "  @Subcomponent.Builder",
92         "  static interface Builder {",
93         "    ChildComponent build();",
94         "  }",
95         "}");
96     assertAbout(javaSources()).that(ImmutableList.of(componentFile, childComponentFile))
97         .processedWith(new ComponentProcessor())
98         .failsToCompile()
99         .withErrorContaining(String.format(MSGS.moreThanOneRefToSubcomponent(),
100             "test.ChildComponent", "[builder1(), builder2()]"))
101         .in(componentFile);
102   }
103 
104   @Test
testMoreThanOneBuilderFails()105   public void testMoreThanOneBuilderFails() {
106     JavaFileObject componentFile = JavaFileObjects.forSourceLines("test.ParentComponent",
107         "package test;",
108         "",
109         "import dagger.Component;",
110         "",
111         "import javax.inject.Provider;",
112         "",
113         "@Component",
114         "interface ParentComponent {",
115         "  ChildComponent.Builder1 build();",
116         "}");
117     JavaFileObject childComponentFile = JavaFileObjects.forSourceLines("test.ChildComponent",
118         "package test;",
119         "",
120         "import dagger.Subcomponent;",
121         "",
122         "@Subcomponent",
123         "interface ChildComponent {",
124         "  @Subcomponent.Builder",
125         "  static interface Builder1 {",
126         "    ChildComponent build();",
127         "  }",
128         "",
129         "  @Subcomponent.Builder",
130         "  static interface Builder2 {",
131         "    ChildComponent build();",
132         "  }",
133         "}");
134     assertAbout(javaSources()).that(ImmutableList.of(componentFile, childComponentFile))
135         .processedWith(new ComponentProcessor())
136         .failsToCompile()
137         .withErrorContaining(String.format(MSGS.moreThanOne(),
138             "[test.ChildComponent.Builder1, test.ChildComponent.Builder2]"))
139         .in(childComponentFile);
140   }
141 
142   @Test
testBuilderGenericsFails()143   public void testBuilderGenericsFails() {
144     JavaFileObject componentFile = JavaFileObjects.forSourceLines("test.ParentComponent",
145         "package test;",
146         "",
147         "import dagger.Component;",
148         "",
149         "import javax.inject.Provider;",
150         "",
151         "@Component",
152         "interface ParentComponent {",
153         "  ChildComponent.Builder1 build();",
154         "}");
155     JavaFileObject childComponentFile = JavaFileObjects.forSourceLines("test.ChildComponent",
156         "package test;",
157         "",
158         "import dagger.Subcomponent;",
159         "",
160         "@Subcomponent",
161         "interface ChildComponent {",
162         "  @Subcomponent.Builder",
163         "  interface Builder<T> {",
164         "     ChildComponent build();",
165         "  }",
166         "}");
167     assertAbout(javaSources()).that(ImmutableList.of(componentFile, childComponentFile))
168         .processedWith(new ComponentProcessor())
169         .failsToCompile()
170         .withErrorContaining(MSGS.generics())
171         .in(childComponentFile);
172   }
173 
174   @Test
testBuilderNotInComponentFails()175   public void testBuilderNotInComponentFails() {
176     JavaFileObject builder = JavaFileObjects.forSourceLines("test.Builder",
177         "package test;",
178         "",
179         "import dagger.Subcomponent;",
180         "",
181         "@Subcomponent.Builder",
182         "interface Builder {}");
183     assertAbout(javaSource()).that(builder)
184         .processedWith(new ComponentProcessor())
185         .failsToCompile()
186         .withErrorContaining(MSGS.mustBeInComponent())
187         .in(builder);
188   }
189 
190   @Test
testBuilderMissingBuildMethodFails()191   public void testBuilderMissingBuildMethodFails() {
192     JavaFileObject componentFile = JavaFileObjects.forSourceLines("test.ParentComponent",
193         "package test;",
194         "",
195         "import dagger.Component;",
196         "",
197         "import javax.inject.Provider;",
198         "",
199         "@Component",
200         "interface ParentComponent {",
201         "  ChildComponent.Builder1 build();",
202         "}");
203     JavaFileObject childComponentFile = JavaFileObjects.forSourceLines("test.ChildComponent",
204         "package test;",
205         "",
206         "import dagger.Subcomponent;",
207         "",
208         "@Subcomponent",
209         "interface ChildComponent {",
210         "  @Subcomponent.Builder",
211         "  interface Builder {}",
212         "}");
213     assertAbout(javaSources()).that(ImmutableList.of(componentFile, childComponentFile))
214         .processedWith(new ComponentProcessor())
215         .failsToCompile()
216         .withErrorContaining(MSGS.missingBuildMethod())
217         .in(childComponentFile);
218   }
219 
220   @Test
testPrivateBuilderFails()221   public void testPrivateBuilderFails() {
222     JavaFileObject childComponentFile = JavaFileObjects.forSourceLines("test.ChildComponent",
223         "package test;",
224         "",
225         "import dagger.Subcomponent;",
226         "",
227         "@Subcomponent",
228         "abstract class ChildComponent {",
229         "  @Subcomponent.Builder",
230         "  private interface Builder {}",
231         "}");
232     assertAbout(javaSources()).that(ImmutableList.of(childComponentFile))
233         .processedWith(new ComponentProcessor())
234         .failsToCompile()
235         .withErrorContaining(MSGS.isPrivate())
236         .in(childComponentFile);
237   }
238 
239   @Test
testNonStaticBuilderFails()240   public void testNonStaticBuilderFails() {
241     JavaFileObject childComponentFile = JavaFileObjects.forSourceLines("test.ChildComponent",
242         "package test;",
243         "",
244         "import dagger.Subcomponent;",
245         "",
246         "@Subcomponent",
247         "abstract class ChildComponent {",
248         "  @Subcomponent.Builder",
249         "  abstract class Builder {}",
250         "}");
251     assertAbout(javaSources()).that(ImmutableList.of(childComponentFile))
252         .processedWith(new ComponentProcessor())
253         .failsToCompile()
254         .withErrorContaining(MSGS.mustBeStatic())
255         .in(childComponentFile);
256   }
257 
258   @Test
testNonAbstractBuilderFails()259   public void testNonAbstractBuilderFails() {
260     JavaFileObject childComponentFile = JavaFileObjects.forSourceLines("test.ChildComponent",
261         "package test;",
262         "",
263         "import dagger.Subcomponent;",
264         "",
265         "@Subcomponent",
266         "abstract class ChildComponent {",
267         "  @Subcomponent.Builder",
268         "  static class Builder {}",
269         "}");
270     assertAbout(javaSources()).that(ImmutableList.of(childComponentFile))
271         .processedWith(new ComponentProcessor())
272         .failsToCompile()
273         .withErrorContaining(MSGS.mustBeAbstract())
274         .in(childComponentFile);
275   }
276 
277   @Test
testBuilderOneCxtorWithArgsFails()278   public void testBuilderOneCxtorWithArgsFails() {
279     JavaFileObject childComponentFile = JavaFileObjects.forSourceLines("test.ChildComponent",
280         "package test;",
281         "",
282         "import dagger.Subcomponent;",
283         "",
284         "@Subcomponent",
285         "abstract class ChildComponent {",
286         "  @Subcomponent.Builder",
287         "  static abstract class Builder {",
288         "    Builder(String unused) {}",
289         "  }",
290         "}");
291     assertAbout(javaSources()).that(ImmutableList.of(childComponentFile))
292         .processedWith(new ComponentProcessor())
293         .failsToCompile()
294         .withErrorContaining(MSGS.cxtorOnlyOneAndNoArgs())
295         .in(childComponentFile);
296   }
297 
298   @Test
testBuilderMoreThanOneCxtorFails()299   public void testBuilderMoreThanOneCxtorFails() {
300     JavaFileObject childComponentFile = JavaFileObjects.forSourceLines("test.ChildComponent",
301         "package test;",
302         "",
303         "import dagger.Subcomponent;",
304         "",
305         "@Subcomponent",
306         "abstract class ChildComponent {",
307         "  @Subcomponent.Builder",
308         "  static abstract class Builder {",
309         "    Builder() {}",
310         "    Builder(String unused) {}",
311         "  }",
312         "}");
313     assertAbout(javaSources()).that(ImmutableList.of(childComponentFile))
314         .processedWith(new ComponentProcessor())
315         .failsToCompile()
316         .withErrorContaining(MSGS.cxtorOnlyOneAndNoArgs())
317         .in(childComponentFile);
318   }
319 
320   @Test
testBuilderEnumFails()321   public void testBuilderEnumFails() {
322     JavaFileObject childComponentFile = JavaFileObjects.forSourceLines("test.ChildComponent",
323         "package test;",
324         "",
325         "import dagger.Subcomponent;",
326         "",
327         "@Subcomponent",
328         "abstract class ChildComponent {",
329         "  @Subcomponent.Builder",
330         "  enum Builder {}",
331         "}");
332     assertAbout(javaSources()).that(ImmutableList.of(childComponentFile))
333         .processedWith(new ComponentProcessor())
334         .failsToCompile()
335         .withErrorContaining(MSGS.mustBeClassOrInterface())
336         .in(childComponentFile);
337   }
338 
339   @Test
testBuilderBuildReturnsWrongTypeFails()340   public void testBuilderBuildReturnsWrongTypeFails() {
341     JavaFileObject childComponentFile = JavaFileObjects.forSourceLines("test.ChildComponent",
342         "package test;",
343         "",
344         "import dagger.Subcomponent;",
345         "",
346         "@Subcomponent",
347         "abstract class ChildComponent {",
348         "  @Subcomponent.Builder",
349         "  interface Builder {",
350         "    String build();",
351         "  }",
352         "}");
353     assertAbout(javaSources()).that(ImmutableList.of(childComponentFile))
354         .processedWith(new ComponentProcessor())
355         .failsToCompile()
356         .withErrorContaining(MSGS.buildMustReturnComponentType())
357             .in(childComponentFile).onLine(9);
358   }
359 
360   @Test
testInheritedBuilderBuildReturnsWrongTypeFails()361   public void testInheritedBuilderBuildReturnsWrongTypeFails() {
362     JavaFileObject childComponentFile = JavaFileObjects.forSourceLines("test.ChildComponent",
363         "package test;",
364         "",
365         "import dagger.Subcomponent;",
366         "",
367         "@Subcomponent",
368         "abstract class ChildComponent {",
369         "  interface Parent {",
370         "    String build();",
371         "  }",
372         "",
373         "  @Subcomponent.Builder",
374         "  interface Builder extends Parent {}",
375         "}");
376     assertAbout(javaSources()).that(ImmutableList.of(childComponentFile))
377         .processedWith(new ComponentProcessor())
378         .failsToCompile()
379         .withErrorContaining(
380             String.format(MSGS.inheritedBuildMustReturnComponentType(), "build"))
381             .in(childComponentFile).onLine(12);
382   }
383 
384   @Test
testTwoBuildMethodsFails()385   public void testTwoBuildMethodsFails() {
386     JavaFileObject childComponentFile = JavaFileObjects.forSourceLines("test.ChildComponent",
387         "package test;",
388         "",
389         "import dagger.Subcomponent;",
390         "",
391         "@Subcomponent",
392         "abstract class ChildComponent {",
393         "  @Subcomponent.Builder",
394         "  interface Builder {",
395         "    ChildComponent build();",
396         "    ChildComponent create();",
397         "  }",
398         "}");
399     assertAbout(javaSources()).that(ImmutableList.of(childComponentFile))
400         .processedWith(new ComponentProcessor())
401         .failsToCompile()
402         .withErrorContaining(String.format(MSGS.twoBuildMethods(), "build()"))
403             .in(childComponentFile).onLine(10);
404   }
405 
406   @Test
testInheritedTwoBuildMethodsFails()407   public void testInheritedTwoBuildMethodsFails() {
408     JavaFileObject childComponentFile = JavaFileObjects.forSourceLines("test.ChildComponent",
409         "package test;",
410         "",
411         "import dagger.Subcomponent;",
412         "",
413         "@Subcomponent",
414         "abstract class ChildComponent {",
415         "  interface Parent {",
416         "    ChildComponent build();",
417         "    ChildComponent create();",
418         "  }",
419         "",
420         "  @Subcomponent.Builder",
421         "  interface Builder extends Parent {}",
422         "}");
423     assertAbout(javaSources()).that(ImmutableList.of(childComponentFile))
424         .processedWith(new ComponentProcessor())
425         .failsToCompile()
426         .withErrorContaining(
427             String.format(MSGS.inheritedTwoBuildMethods(), "create()", "build()"))
428             .in(childComponentFile).onLine(13);
429   }
430 
431   @Test
testMoreThanOneArgFails()432   public void testMoreThanOneArgFails() {
433     JavaFileObject childComponentFile = JavaFileObjects.forSourceLines("test.ChildComponent",
434         "package test;",
435         "",
436         "import dagger.Subcomponent;",
437         "",
438         "@Subcomponent",
439         "abstract class ChildComponent {",
440         "  @Subcomponent.Builder",
441         "  interface Builder {",
442         "    ChildComponent build();",
443         "    Builder set(String s, Integer i);",
444         "    Builder set(Number n, Double d);",
445         "  }",
446         "}");
447     assertAbout(javaSources()).that(ImmutableList.of(childComponentFile))
448         .processedWith(new ComponentProcessor())
449         .failsToCompile()
450         .withErrorContaining(MSGS.methodsMustTakeOneArg())
451             .in(childComponentFile).onLine(10)
452         .and().withErrorContaining(MSGS.methodsMustTakeOneArg())
453             .in(childComponentFile).onLine(11);
454   }
455 
456   @Test
testInheritedMoreThanOneArgFails()457   public void testInheritedMoreThanOneArgFails() {
458     JavaFileObject childComponentFile = JavaFileObjects.forSourceLines("test.ChildComponent",
459         "package test;",
460         "",
461         "import dagger.Subcomponent;",
462         "",
463         "@Subcomponent",
464         "abstract class ChildComponent {",
465         "  interface Parent {",
466         "    ChildComponent build();",
467         "    Builder set1(String s, Integer i);",
468         "  }",
469         "",
470         "  @Subcomponent.Builder",
471         "  interface Builder extends Parent {}",
472         "}");
473     assertAbout(javaSources()).that(ImmutableList.of(childComponentFile))
474         .processedWith(new ComponentProcessor())
475         .failsToCompile()
476         .withErrorContaining(
477             String.format(MSGS.inheritedMethodsMustTakeOneArg(),
478                 "set1(java.lang.String,java.lang.Integer)"))
479             .in(childComponentFile).onLine(13);
480   }
481 
482   @Test
testSetterReturningNonVoidOrBuilderFails()483   public void testSetterReturningNonVoidOrBuilderFails() {
484     JavaFileObject childComponentFile = JavaFileObjects.forSourceLines("test.ChildComponent",
485         "package test;",
486         "",
487         "import dagger.Subcomponent;",
488         "",
489         "@Subcomponent",
490         "abstract class ChildComponent {",
491         "  @Subcomponent.Builder",
492         "  interface Builder {",
493         "    ChildComponent build();",
494         "    String set(Integer i);",
495         "  }",
496         "}");
497     assertAbout(javaSources()).that(ImmutableList.of(childComponentFile))
498         .processedWith(new ComponentProcessor())
499         .failsToCompile()
500         .withErrorContaining(MSGS.methodsMustReturnVoidOrBuilder())
501             .in(childComponentFile).onLine(10);
502   }
503 
504   @Test
testInheritedSetterReturningNonVoidOrBuilderFails()505   public void testInheritedSetterReturningNonVoidOrBuilderFails() {
506     JavaFileObject childComponentFile = JavaFileObjects.forSourceLines("test.ChildComponent",
507         "package test;",
508         "",
509         "import dagger.Subcomponent;",
510         "",
511         "@Subcomponent",
512         "abstract class ChildComponent {",
513         "  interface Parent {",
514         "    ChildComponent build();",
515         "    String set(Integer i);",
516         "  }",
517         "",
518         "  @Subcomponent.Builder",
519         "  interface Builder extends Parent {}",
520         "}");
521     assertAbout(javaSources()).that(ImmutableList.of(childComponentFile))
522         .processedWith(new ComponentProcessor())
523         .failsToCompile()
524         .withErrorContaining(
525             String.format(MSGS.inheritedMethodsMustReturnVoidOrBuilder(),
526                 "set(java.lang.Integer)"))
527             .in(childComponentFile).onLine(13);
528   }
529 
530   @Test
testGenericsOnSetterMethodFails()531   public void testGenericsOnSetterMethodFails() {
532     JavaFileObject childComponentFile = JavaFileObjects.forSourceLines("test.ChildComponent",
533         "package test;",
534         "",
535         "import dagger.Subcomponent;",
536         "",
537         "@Subcomponent",
538         "abstract class ChildComponent {",
539         "  @Subcomponent.Builder",
540         "  interface Builder {",
541         "    ChildComponent build();",
542         "    <T> Builder set(T t);",
543         "  }",
544         "}");
545     assertAbout(javaSources()).that(ImmutableList.of(childComponentFile))
546         .processedWith(new ComponentProcessor())
547         .failsToCompile()
548         .withErrorContaining(MSGS.methodsMayNotHaveTypeParameters())
549             .in(childComponentFile).onLine(10);
550   }
551 
552   @Test
testGenericsOnInheritedSetterMethodFails()553   public void testGenericsOnInheritedSetterMethodFails() {
554     JavaFileObject childComponentFile = JavaFileObjects.forSourceLines("test.ChildComponent",
555         "package test;",
556         "",
557         "import dagger.Subcomponent;",
558         "",
559         "@Subcomponent",
560         "abstract class ChildComponent {",
561         "  interface Parent {",
562         "    ChildComponent build();",
563         "    <T> Builder set(T t);",
564         "  }",
565         "",
566         "  @Subcomponent.Builder",
567         "  interface Builder extends Parent {}",
568         "}");
569     assertAbout(javaSources()).that(ImmutableList.of(childComponentFile))
570         .processedWith(new ComponentProcessor())
571         .failsToCompile()
572         .withErrorContaining(
573             String.format(MSGS.inheritedMethodsMayNotHaveTypeParameters(), "<T>set(T)"))
574             .in(childComponentFile).onLine(13);
575   }
576 
577   @Test
testMultipleSettersPerTypeFails()578   public void testMultipleSettersPerTypeFails() {
579     JavaFileObject childComponentFile = JavaFileObjects.forSourceLines("test.ChildComponent",
580         "package test;",
581         "",
582         "import dagger.Subcomponent;",
583         "",
584         "@Subcomponent",
585         "abstract class ChildComponent {",
586         "  @Subcomponent.Builder",
587         "  interface Builder {",
588         "    ChildComponent build();",
589         "    void set1(String s);",
590         "    void set2(String s);",
591         "  }",
592         "}");
593     assertAbout(javaSources()).that(ImmutableList.of(childComponentFile))
594         .processedWith(new ComponentProcessor())
595         .failsToCompile()
596         .withErrorContaining(
597             String.format(MSGS.manyMethodsForType(),
598                   "java.lang.String", "[set1(java.lang.String), set2(java.lang.String)]"))
599             .in(childComponentFile).onLine(8);
600   }
601 
602   @Test
testMultipleSettersPerTypeIncludingResolvedGenericsFails()603   public void testMultipleSettersPerTypeIncludingResolvedGenericsFails() {
604     JavaFileObject childComponentFile = JavaFileObjects.forSourceLines("test.ChildComponent",
605         "package test;",
606         "",
607         "import dagger.Subcomponent;",
608         "",
609         "@Subcomponent",
610         "abstract class ChildComponent {",
611         "  interface Parent<T> {",
612         "    void set1(T t);",
613         "  }",
614         "",
615         "  @Subcomponent.Builder",
616         "  interface Builder extends Parent<String> {",
617         "    ChildComponent build();",
618         "    void set2(String s);",
619         "  }",
620         "}");
621     assertAbout(javaSources()).that(ImmutableList.of(childComponentFile))
622         .processedWith(new ComponentProcessor())
623         .failsToCompile()
624         .withErrorContaining(
625             String.format(MSGS.manyMethodsForType(),
626                   "java.lang.String", "[set1(T), set2(java.lang.String)]"))
627             .in(childComponentFile).onLine(12);
628   }
629 
630   @Test
testExtraSettersFails()631   public void testExtraSettersFails() {
632     JavaFileObject componentFile = JavaFileObjects.forSourceLines("test.ParentComponent",
633         "package test;",
634         "",
635         "import dagger.Component;",
636         "",
637         "import javax.inject.Provider;",
638         "",
639         "@Component",
640         "interface ParentComponent {",
641         "  ChildComponent.Builder build();",
642         "}");
643     JavaFileObject childComponentFile = JavaFileObjects.forSourceLines("test.ChildComponent",
644         "package test;",
645         "",
646         "import dagger.Subcomponent;",
647         "",
648         "@Subcomponent",
649         "interface ChildComponent {",
650         "  @Subcomponent.Builder",
651         "  interface Builder {",
652         "    ChildComponent build();",
653         "    void set1(String s);",
654         "    void set2(Integer s);",
655         "  }",
656         "}");
657     assertAbout(javaSources()).that(ImmutableList.of(componentFile, childComponentFile))
658         .processedWith(new ComponentProcessor())
659         .failsToCompile()
660         .withErrorContaining(
661             String.format(MSGS.extraSetters(),
662                   "[void test.ChildComponent.Builder.set1(String),"
663                   + " void test.ChildComponent.Builder.set2(Integer)]"))
664             .in(childComponentFile).onLine(8);
665 
666   }
667 
668   @Test
testMissingSettersFail()669   public void testMissingSettersFail() {
670     JavaFileObject moduleFile = JavaFileObjects.forSourceLines("test.TestModule",
671         "package test;",
672         "",
673         "import dagger.Module;",
674         "import dagger.Provides;",
675         "",
676         "@Module",
677         "final class TestModule {",
678         "  TestModule(String unused) {}",
679         "  @Provides String s() { return null; }",
680         "}");
681     JavaFileObject module2File = JavaFileObjects.forSourceLines("test.Test2Module",
682         "package test;",
683         "",
684         "import dagger.Module;",
685         "import dagger.Provides;",
686         "",
687         "@Module",
688         "final class Test2Module {",
689         "  @Provides Integer i() { return null; }",
690         "}");
691     JavaFileObject module3File = JavaFileObjects.forSourceLines("test.Test3Module",
692         "package test;",
693         "",
694         "import dagger.Module;",
695         "import dagger.Provides;",
696         "",
697         "@Module",
698         "final class Test3Module {",
699         "  Test3Module(String unused) {}",
700         "  @Provides Double d() { return null; }",
701         "}");
702     JavaFileObject componentFile = JavaFileObjects.forSourceLines("test.ParentComponent",
703         "package test;",
704         "",
705         "import dagger.Component;",
706         "",
707         "import javax.inject.Provider;",
708         "",
709         "@Component",
710         "interface ParentComponent {",
711         "  ChildComponent.Builder build();",
712         "}");
713     JavaFileObject childComponentFile = JavaFileObjects.forSourceLines("test.ChildComponent",
714         "package test;",
715         "",
716         "import dagger.Subcomponent;",
717         "",
718         "@Subcomponent(modules = {TestModule.class, Test2Module.class, Test3Module.class})",
719         "interface ChildComponent {",
720         "  String string();",
721         "  Integer integer();",
722         "",
723         "  @Subcomponent.Builder",
724         "  interface Builder {",
725         "    ChildComponent create();",
726         "  }",
727         "}");
728     assertAbout(javaSources())
729         .that(ImmutableList.of(moduleFile,
730             module2File,
731             module3File,
732             componentFile,
733             childComponentFile))
734         .processedWith(new ComponentProcessor())
735         .failsToCompile()
736         .withErrorContaining(
737             // Ignores Test2Module because we can construct it ourselves.
738             // TODO(sameb): Ignore Test3Module because it's not used within transitive dependencies.
739             String.format(MSGS.missingSetters(), "[test.TestModule, test.Test3Module]"))
740             .in(childComponentFile).onLine(11);
741   }
742 }
743