/* * Copyright (C) 2015 Google, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package dagger.internal.codegen; import com.google.common.base.Joiner; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; import com.google.testing.compile.JavaFileObjects; import java.io.IOException; import java.io.Writer; import java.util.Set; import javax.annotation.processing.AbstractProcessor; import javax.annotation.processing.RoundEnvironment; import javax.lang.model.element.TypeElement; import javax.tools.JavaFileObject; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; import static com.google.common.truth.Truth.assertAbout; import static com.google.testing.compile.JavaSourceSubjectFactory.javaSource; import static com.google.testing.compile.JavaSourcesSubjectFactory.javaSources; import static javax.tools.StandardLocation.CLASS_OUTPUT; @RunWith(JUnit4.class) public class MembersInjectionTest { @Test public void parentClass_noInjectedMembers() { JavaFileObject childFile = JavaFileObjects.forSourceLines("test.Child", "package test;", "", "import javax.inject.Inject;", "", "public final class Child extends Parent {", " @Inject Child() {}", "}"); JavaFileObject parentFile = JavaFileObjects.forSourceLines("test.Parent", "package test;", "", "public abstract class Parent {}"); JavaFileObject componentFile = JavaFileObjects.forSourceLines("test.TestComponent", "package test;", "", "import dagger.Component;", "", "", "@Component", "interface TestComponent {", " Child child();", "}"); JavaFileObject generatedComponent = JavaFileObjects.forSourceLines( "test.DaggerTestComponent", "package test;", "", "import dagger.MembersInjector;", "import dagger.internal.MembersInjectors;", "import javax.annotation.Generated;", "import javax.inject.Provider;", "", "@Generated(\"dagger.internal.codegen.ComponentProcessor\")", "public final class DaggerTestComponent implements TestComponent {", " private Provider<Child> childProvider;", "", " private DaggerTestComponent(Builder builder) {", " assert builder != null;", " initialize(builder);", " }", "", " public static Builder builder() {", " return new Builder();", " }", "", " public static TestComponent create() {", " return builder().build();", " }", "", " @SuppressWarnings(\"unchecked\")", " private void initialize(final Builder builder) {", " this.childProvider =", " Child_Factory.create((MembersInjector) MembersInjectors.noOp());", " }", "", " @Override", " public Child child() {", " return childProvider.get();", " }", "", " public static final class Builder {", " private Builder() {", " }", "", " public TestComponent build() {", " return new DaggerTestComponent(this);", " }", " }", "}"); assertAbout(javaSources()) .that(ImmutableList.of(childFile, parentFile, componentFile)) .processedWith(new ComponentProcessor()) .compilesWithoutError() .and().generatesSources(generatedComponent); } @Test public void parentClass_injectedMembersInSupertype() { JavaFileObject childFile = JavaFileObjects.forSourceLines("test.Child", "package test;", "", "import javax.inject.Inject;", "", "public final class Child extends Parent {", " @Inject Child() {}", "}"); JavaFileObject parentFile = JavaFileObjects.forSourceLines("test.Parent", "package test;", "", "import javax.inject.Inject;", "", "public abstract class Parent {", " @Inject Dep dep;", "}"); JavaFileObject depFile = JavaFileObjects.forSourceLines("test.Dep", "package test;", "", "import javax.inject.Inject;", "", "final class Dep {", " @Inject Dep() {}", "}"); JavaFileObject componentFile = JavaFileObjects.forSourceLines("test.TestComponent", "package test;", "", "import dagger.Component;", "", "", "@Component", "interface TestComponent {", " Child child();", "}"); JavaFileObject generatedComponent = JavaFileObjects.forSourceLines( "test.DaggerTestComponent", "package test;", "", "import dagger.MembersInjector;", "import javax.annotation.Generated;", "import javax.inject.Provider;", "", "@Generated(\"dagger.internal.codegen.ComponentProcessor\")", "public final class DaggerTestComponent implements TestComponent {", " private MembersInjector<Child> childMembersInjector;", " private Provider<Child> childProvider;", "", " private DaggerTestComponent(Builder builder) {", " assert builder != null;", " initialize(builder);", " }", "", " public static Builder builder() {", " return new Builder();", " }", "", " public static TestComponent create() {", " return builder().build();", " }", "", " @SuppressWarnings(\"unchecked\")", " private void initialize(final Builder builder) {", " this.childMembersInjector = Child_MembersInjector.create(Dep_Factory.create());", " this.childProvider = Child_Factory.create(childMembersInjector);", " }", "", " @Override", " public Child child() {", " return childProvider.get();", " }", "", " public static final class Builder {", " private Builder() {}", "", " public TestComponent build() {", " return new DaggerTestComponent(this);", " }", " }", "}"); assertAbout(javaSources()) .that(ImmutableList.of(childFile, parentFile, depFile, componentFile)) .processedWith(new ComponentProcessor()) .compilesWithoutError() .and() .generatesSources(generatedComponent); } @Test public void fieldAndMethodGenerics() { JavaFileObject file = JavaFileObjects.forSourceLines("test.GenericClass", "package test;", "", "import javax.inject.Inject;", "", "class GenericClass<A, B> {", " @Inject A a;", "", " @Inject GenericClass() {}", "", " @Inject void register(B b) {}", "}"); JavaFileObject expected = JavaFileObjects.forSourceLines( "test.GenericClass_MembersInjector", "package test;", "", "import dagger.MembersInjector;", "import javax.annotation.Generated;", "import javax.inject.Provider;", "", "@Generated(\"dagger.internal.codegen.ComponentProcessor\")", "public final class GenericClass_MembersInjector<A, B>", " implements MembersInjector<GenericClass<A, B>> {", " private final Provider<A> aProvider;", " private final Provider<B> bProvider;", "", " public GenericClass_MembersInjector(Provider<A> aProvider, Provider<B> bProvider) {", " assert aProvider != null;", " this.aProvider = aProvider;", " assert bProvider != null;", " this.bProvider = bProvider;", " }", "", " @Override", " public void injectMembers(GenericClass<A, B> instance) {", " if (instance == null) {", " throw new NullPointerException(\"Cannot inject members into a null reference\");", " }", " instance.a = aProvider.get();", " instance.register(bProvider.get());", " }", "", " public static <A, B> MembersInjector<GenericClass<A, B>> create(", " Provider<A> aProvider, Provider<B> bProvider) {", " return new GenericClass_MembersInjector<A, B>(aProvider, bProvider);", " }", "", " public static <A, B> void injectA(GenericClass<A, B> instance, Provider<A> aProvider) {", " instance.a = aProvider.get();", " }", "", " public static <A, B> void injectRegister(", " GenericClass<A, B> instance, Provider<B> bProvider) {", " instance.register(bProvider.get());", " }", "", "}"); assertAbout(javaSource()) .that(file) .processedWith(new ComponentProcessor()) .compilesWithoutError() .and() .generatesSources(expected); } @Test public void subclassedGenericMembersInjectors() { JavaFileObject a = JavaFileObjects.forSourceLines("test.A", "package test;", "", "import javax.inject.Inject;", "", "final class A {", " @Inject A() {}", "}"); JavaFileObject a2 = JavaFileObjects.forSourceLines("test.A2", "package test;", "", "import javax.inject.Inject;", "", "final class A2 {", " @Inject A2() {}", "}"); JavaFileObject parent = JavaFileObjects.forSourceLines("test.Parent", "package test;", "", "import javax.inject.Inject;", "", "class Parent<X, Y> {", " @Inject X x;", " @Inject Y y;", " @Inject A2 a2;", "", " @Inject Parent() {}", "}"); JavaFileObject child = JavaFileObjects.forSourceLines("test.Child", "package test;", "", "import javax.inject.Inject;", "", "class Child<T> extends Parent<T, A> {", " @Inject A a;", " @Inject T t;", "", " @Inject Child() {}", "}"); JavaFileObject expected = JavaFileObjects.forSourceLines( "test.Child_MembersInjector", "package test;", "", "import dagger.MembersInjector;", "import javax.annotation.Generated;", "import javax.inject.Provider;", "", "@Generated(\"dagger.internal.codegen.ComponentProcessor\")", "public final class Child_MembersInjector<T>", " implements MembersInjector<Child<T>> {", " private final Provider<T> tAndXProvider;", " private final Provider<A> aAndYProvider;", " private final Provider<A2> a2Provider;", "", " public Child_MembersInjector(", " Provider<T> tAndXProvider, Provider<A> aAndYProvider, Provider<A2> a2Provider) {", " assert tAndXProvider != null;", " this.tAndXProvider = tAndXProvider;", " assert aAndYProvider != null;", " this.aAndYProvider = aAndYProvider;", " assert a2Provider != null;", " this.a2Provider = a2Provider;", " }", "", " @Override", " public void injectMembers(Child<T> instance) {", " if (instance == null) {", " throw new NullPointerException(\"Cannot inject members into a null reference\");", " }", " ((test.Parent) instance).x = tAndXProvider.get();", " ((test.Parent) instance).y = aAndYProvider.get();", " ((test.Parent) instance).a2 = a2Provider.get();", " instance.a = aAndYProvider.get();", " instance.t = tAndXProvider.get();", " }", "", " public static <T> MembersInjector<Child<T>> create(", " Provider<T> tAndXProvider, Provider<A> aAndYProvider, Provider<A2> a2Provider) {", " return new Child_MembersInjector<T>(tAndXProvider, aAndYProvider, a2Provider);", " }", "", " public static <T> void injectA(Child<T> instance, Provider<A> aProvider) {", " instance.a = aProvider.get();", " }", "", " public static <T> void injectT(Child<T> instance, Provider<T> tProvider) {", " instance.t = tProvider.get();", " }", "}"); assertAbout(javaSources()) .that(ImmutableList.of(a, a2, parent, child)) .processedWith(new ComponentProcessor()) .compilesWithoutError() .and() .generatesSources(expected); } @Test public void fieldInjection() { JavaFileObject file = JavaFileObjects.forSourceLines("test.FieldInjection", "package test;", "", "import dagger.Lazy;", "import javax.inject.Inject;", "import javax.inject.Provider;", "", "class FieldInjection {", " @Inject String string;", " @Inject Lazy<String> lazyString;", " @Inject Provider<String> stringProvider;", "}"); JavaFileObject expected = JavaFileObjects.forSourceLines( "test.FieldInjection_MembersInjector", "package test;", "", "import dagger.MembersInjector;", "import dagger.internal.DoubleCheckLazy;", "import javax.annotation.Generated;", "import javax.inject.Provider;", "", "@Generated(\"dagger.internal.codegen.ComponentProcessor\")", "public final class FieldInjection_MembersInjector", " implements MembersInjector<FieldInjection> {", " private final Provider<String> stringProvider;", "", " public FieldInjection_MembersInjector(Provider<String> stringProvider) {", " assert stringProvider != null;", " this.stringProvider = stringProvider;", " }", "", " @Override", " public void injectMembers(FieldInjection instance) {", " if (instance == null) {", " throw new NullPointerException(\"Cannot inject members into a null reference\");", " }", " instance.string = stringProvider.get();", " instance.lazyString = DoubleCheckLazy.create(stringProvider);", " instance.stringProvider = stringProvider;", " }", "", " public static MembersInjector<FieldInjection> create(Provider<String> stringProvider) {", " return new FieldInjection_MembersInjector(stringProvider);", " }", "", " public static void injectString(", " FieldInjection instance, Provider<String> stringProvider) {", " instance.string = stringProvider.get();", " }", "", " public static void injectLazyString(", " FieldInjection instance, Provider<String> lazyStringProvider) {", " instance.lazyString = DoubleCheckLazy.create(lazyStringProvider);", " }", "", " public static void injectStringProvider(", " FieldInjection instance, Provider<String> stringProvider) {", " instance.stringProvider = stringProvider;", " }", "}"); assertAbout(javaSource()) .that(file) .processedWith(new ComponentProcessor()) .compilesWithoutError() .and() .generatesSources(expected); } @Test public void methodInjection() { JavaFileObject file = JavaFileObjects.forSourceLines("test.MethodInjection", "package test;", "", "import dagger.Lazy;", "import javax.inject.Inject;", "import javax.inject.Provider;", "", "class MethodInjection {", " @Inject void noArgs() {}", " @Inject void oneArg(String string) {}", " @Inject void manyArgs(", " String string, Lazy<String> lazyString, Provider<String> stringProvider) {}", "}"); JavaFileObject expected = JavaFileObjects.forSourceLines( "test.MethodInjection_MembersInjector", "package test;", "", "import dagger.MembersInjector;", "import dagger.internal.DoubleCheckLazy;", "import javax.annotation.Generated;", "import javax.inject.Provider;", "", "@Generated(\"dagger.internal.codegen.ComponentProcessor\")", "public final class MethodInjection_MembersInjector", " implements MembersInjector<MethodInjection> {", "", " private final Provider<String> stringProvider;", "", " public MethodInjection_MembersInjector(Provider<String> stringProvider) {", " assert stringProvider != null;", " this.stringProvider = stringProvider;", " }", "", " @Override", " public void injectMembers(MethodInjection instance) {", " if (instance == null) {", " throw new NullPointerException(\"Cannot inject members into a null reference\");", " }", " instance.noArgs();", " instance.oneArg(stringProvider.get());", " instance.manyArgs(stringProvider.get(), DoubleCheckLazy.create(stringProvider),", " stringProvider);", " }", "", " public static MembersInjector<MethodInjection> create(", " Provider<String> stringProvider) {", " return new MethodInjection_MembersInjector(stringProvider);", " }", "", " public static void injectNoArgs(MethodInjection instance) {", " instance.noArgs();", " }", "", " public static void injectOneArg(", " MethodInjection instance, Provider<String> stringProvider) {", " instance.oneArg(stringProvider.get());", " }", "", " public static void injectManyArgs(", " MethodInjection instance,", " Provider<String> stringProvider,", " Provider<String> lazyStringProvider,", " Provider<String> stringProvider2) {", " instance.manyArgs(", " stringProvider.get(),", " DoubleCheckLazy.create(lazyStringProvider),", " stringProvider2);", " }", "}"); assertAbout(javaSource()) .that(file) .processedWith(new ComponentProcessor()) .compilesWithoutError() .and() .generatesSources(expected); } @Test public void mixedMemberInjection() { JavaFileObject file = JavaFileObjects.forSourceLines( "test.MixedMemberInjection", "package test;", "", "import dagger.Lazy;", "import javax.inject.Inject;", "import javax.inject.Provider;", "", "class MixedMemberInjection {", " @Inject String string;", " @Inject void setString(String s) {}", " @Inject Object object;", " @Inject void setObject(Object o) {}", "}"); JavaFileObject expected = JavaFileObjects.forSourceLines( "test.MixedMemberInjection_MembersInjector", "package test;", "", "import dagger.MembersInjector;", "import javax.annotation.Generated;", "import javax.inject.Provider;", "", "@Generated(\"dagger.internal.codegen.ComponentProcessor\")", "public final class MixedMemberInjection_MembersInjector", " implements MembersInjector<MixedMemberInjection> {", "", " private final Provider<String> stringAndSProvider;", " private final Provider<Object> objectAndOProvider;", "", " public MixedMemberInjection_MembersInjector(", " Provider<String> stringAndSProvider,", " Provider<Object> objectAndOProvider) {", " assert stringAndSProvider != null;", " this.stringAndSProvider = stringAndSProvider;", " assert objectAndOProvider != null;", " this.objectAndOProvider = objectAndOProvider;", " }", "", " @Override", " public void injectMembers(MixedMemberInjection instance) {", " if (instance == null) {", " throw new NullPointerException(\"Cannot inject members into a null reference\");", " }", " instance.string = stringAndSProvider.get();", " instance.object = objectAndOProvider.get();", " instance.setString(stringAndSProvider.get());", " instance.setObject(objectAndOProvider.get());", " }", "", " public static MembersInjector<MixedMemberInjection> create(", " Provider<String> stringAndSProvider,", " Provider<Object> objectAndOProvider) {", " return new MixedMemberInjection_MembersInjector(", " stringAndSProvider, objectAndOProvider);", " }", " public static void injectString(", " MixedMemberInjection instance, Provider<String> stringProvider) {", " instance.string = stringProvider.get();", " }", "", " public static void injectObject(", " MixedMemberInjection instance, Provider<Object> objectProvider) {", " instance.object = objectProvider.get();", " }", "", " public static void injectSetString(", " MixedMemberInjection instance, Provider<String> sProvider) {", " instance.setString(sProvider.get());", " }", "", " public static void injectSetObject(", " MixedMemberInjection instance, Provider<Object> oProvider) {", " instance.setObject(oProvider.get());", " }", "}"); assertAbout(javaSource()) .that(file) .processedWith(new ComponentProcessor()) .compilesWithoutError() .and() .generatesSources(expected); } @Test public void injectConstructorAndMembersInjection() { JavaFileObject file = JavaFileObjects.forSourceLines("test.AllInjections", "package test;", "", "import javax.inject.Inject;", "", "class AllInjections {", " @Inject String s;", " @Inject AllInjections(String s) {}", " @Inject void s(String s) {}", "}"); JavaFileObject expectedMembersInjector = JavaFileObjects.forSourceLines( "test.AllInjections_MembersInjector", "package test;", "", "import dagger.MembersInjector;", "import javax.annotation.Generated;", "import javax.inject.Provider;", "", "@Generated(\"dagger.internal.codegen.ComponentProcessor\")", "public final class AllInjections_MembersInjector ", " implements MembersInjector<AllInjections> {", "", " private final Provider<String> sProvider;", "", " public AllInjections_MembersInjector(Provider<String> sProvider) {", " assert sProvider != null;", " this.sProvider = sProvider;", " }", "", " @Override", " public void injectMembers(AllInjections instance) {", " if (instance == null) {", " throw new NullPointerException(\"Cannot inject members into a null reference\");", " }", " instance.s = sProvider.get();", " instance.s(sProvider.get());", " }", "", " public static MembersInjector<AllInjections> create(Provider<String> sProvider) {", " return new AllInjections_MembersInjector(sProvider);", " }", "", " public static void injectS(AllInjections instance, Provider<String> sProvider) {", " instance.s = sProvider.get();", " }", "}"); assertAbout(javaSource()) .that(file) .processedWith(new ComponentProcessor()) .compilesWithoutError() .and() .generatesSources(expectedMembersInjector); } @Test public void supertypeMembersInjection() { JavaFileObject aFile = JavaFileObjects.forSourceLines("test.A", "package test;", "", "class A {}"); JavaFileObject bFile = JavaFileObjects.forSourceLines("test.B", "package test;", "", "import javax.inject.Inject;", "", "class B extends A {", " @Inject String s;", "}"); JavaFileObject expectedMembersInjector = JavaFileObjects.forSourceLines( "test.AllInjections_MembersInjector", "package test;", "", "import dagger.MembersInjector;", "import javax.annotation.Generated;", "import javax.inject.Provider;", "", "@Generated(\"dagger.internal.codegen.ComponentProcessor\")", "public final class B_MembersInjector implements MembersInjector<B> {", " private final Provider<String> sProvider;", "", " public B_MembersInjector(Provider<String> sProvider) {", " assert sProvider != null;", " this.sProvider = sProvider;", " }", "", " @Override", " public void injectMembers(B instance) {", " if (instance == null) {", " throw new NullPointerException(\"Cannot inject members into a null reference\");", " }", " instance.s = sProvider.get();", " }", "", " public static MembersInjector<B> create(Provider<String> sProvider) {", " return new B_MembersInjector(sProvider);", " }", " public static void injectS(B instance, Provider<String> sProvider) {", " instance.s = sProvider.get();", " }", "}"); assertAbout(javaSources()) .that(ImmutableList.of(aFile, bFile)) .processedWith(new ComponentProcessor()) .compilesWithoutError() .and() .generatesSources(expectedMembersInjector); } @Test public void simpleComponentWithNesting() { JavaFileObject nestedTypesFile = JavaFileObjects.forSourceLines( "test.OuterType", "package test;", "", "import dagger.Component;", "import javax.inject.Inject;", "", "final class OuterType {", " static class A {", " @Inject A() {}", " }", " static class B {", " @Inject A a;", " }", " @Component interface SimpleComponent {", " A a();", " void inject(B b);", " }", "}"); JavaFileObject bMembersInjector = JavaFileObjects.forSourceLines( "test.OuterType$B_MembersInjector", "package test;", "", "import dagger.MembersInjector;", "import javax.annotation.Generated;", "import javax.inject.Provider;", "import test.OuterType.A;", "import test.OuterType.B;", "", "@Generated(\"dagger.internal.codegen.ComponentProcessor\")", "public final class OuterType$B_MembersInjector implements MembersInjector<B> {", " private final Provider<A> aProvider;", "", " public OuterType$B_MembersInjector(Provider<A> aProvider) {", " assert aProvider != null;", " this.aProvider = aProvider;", " }", "", " @Override", " public void injectMembers(B instance) {", " if (instance == null) {", " throw new NullPointerException(\"Cannot inject members into a null reference\");", " }", " instance.a = aProvider.get();", " }", "", " public static MembersInjector<B> create(Provider<A> aProvider) {", " return new OuterType$B_MembersInjector(aProvider);", " }", "", " public static void injectA(B instance, Provider<A> aProvider) {", " instance.a = aProvider.get();", " }", "}"); assertAbout(javaSources()) .that(ImmutableList.of(nestedTypesFile)) .processedWith(new ComponentProcessor()) .compilesWithoutError() .and() .generatesSources(bMembersInjector); } @Test public void componentWithNestingAndGeneratedType() { JavaFileObject nestedTypesFile = JavaFileObjects.forSourceLines( "test.OuterType", "package test;", "", "import dagger.Component;", "import javax.inject.Inject;", "", "final class OuterType {", " @Inject GeneratedType generated;", " static class A {", " @Inject A() {}", " }", " static class B {", " @Inject A a;", " }", " @Component interface SimpleComponent {", " A a();", " void inject(B b);", " }", "}"); JavaFileObject bMembersInjector = JavaFileObjects.forSourceLines( "test.OuterType$B_MembersInjector", "package test;", "", "import dagger.MembersInjector;", "import javax.annotation.Generated;", "import javax.inject.Provider;", "import test.OuterType.A;", "import test.OuterType.B;", "", "@Generated(\"dagger.internal.codegen.ComponentProcessor\")", "public final class OuterType$B_MembersInjector implements MembersInjector<B> {", " private final Provider<A> aProvider;", "", " public OuterType$B_MembersInjector(Provider<A> aProvider) {", " assert aProvider != null;", " this.aProvider = aProvider;", " }", "", " @Override", " public void injectMembers(B instance) {", " if (instance == null) {", " throw new NullPointerException(\"Cannot inject members into a null reference\");", " }", " instance.a = aProvider.get();", " }", "", " public static MembersInjector<B> create(Provider<A> aProvider) {", " return new OuterType$B_MembersInjector(aProvider);", " }", "", " public static void injectA(B instance, Provider<A> aProvider) {", " instance.a = aProvider.get();", " }", "}"); assertAbout(javaSource()) .that(nestedTypesFile) .processedWith( new ComponentProcessor(), new AbstractProcessor() { private boolean done; @Override public Set<String> getSupportedAnnotationTypes() { return ImmutableSet.of("*"); } @Override public boolean process( Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { if (!done) { done = true; try (Writer writer = processingEnv .getFiler() .createSourceFile("test.GeneratedType") .openWriter()) { writer.write( Joiner.on('\n') .join( "package test;", "", "import javax.inject.Inject;", "", "class GeneratedType {", " @Inject GeneratedType() {}", "}")); } catch (IOException e) { throw new RuntimeException(e); } } return false; } }) .compilesWithoutError() .and() .generatesSources(bMembersInjector); } @Test public void lowerCaseNamedMembersInjector_forLowerCaseType() { JavaFileObject foo = JavaFileObjects.forSourceLines( "test.foo", "package test;", "", "import javax.inject.Inject;", "", "class foo {", " @Inject String string;", "}"); JavaFileObject fooModule = JavaFileObjects.forSourceLines( "test.fooModule", "package test;", "", "import dagger.Module;", "import dagger.Provides;", "", "@Module", "class fooModule {", " @Provides String string() { return \"foo\"; }", "}"); JavaFileObject fooComponent = JavaFileObjects.forSourceLines( "test.fooComponent", "package test;", "", "import dagger.Component;", "", "@Component(modules = fooModule.class)", "interface fooComponent {", " void inject(foo target);", "}"); assertAbout(javaSources()) .that(ImmutableList.of(foo, fooModule, fooComponent)) .processedWith(new ComponentProcessor()) .compilesWithoutError() .and().generatesFileNamed(CLASS_OUTPUT, "test", "foo_MembersInjector.class"); } }