Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

@Provides, Injection and Interfaces (Retrofit) #107

Open
ghost opened this issue May 22, 2014 · 3 comments
Open

@Provides, Injection and Interfaces (Retrofit) #107

ghost opened this issue May 22, 2014 · 3 comments
Milestone

Comments

@ghost
Copy link

ghost commented May 22, 2014

I'm trying to use @Provides to return a Singelton of a Retrofit REST API Service.
The @Provides code looks like this:

@TransfuseModule
public class MainModule{
@Provides @Singleton
    @Named(Constants.SERVICE_PRODUCT)
    public ProductService getProductService() {
        Gson gson = new GsonBuilder()
                .setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES)
                .create();

        RequestInterceptor requestInterceptor = new RequestInterceptor() {
            @Override
            public void intercept(RequestFacade request) {
                request.addQueryParam("api_key", "mykey");
            }
        };

        RestAdapter restAdapter = new RestAdapter.Builder()
                .setEndpoint("https://someendpoint.de/api/v1/")
                .setRequestInterceptor(requestInterceptor)
                .setConverter(new GsonConverter(gson))
                .build();

        return restAdapter.create(ProductService.class);
    }
}

The Retrofit Interface looks like this:

public interface ProductService {
    @GET("products/search.json?keyword={keyword}")
    List<Product> listProducts(@Path("keyword") String keyword);
}

Additionally I have set up the following test class with two tests - the first one manually creating the service itself, the second one relying on transfuse injection. The first test passes, the second one fails.
Test code is like this:

@RunWith(RobolectricGradleTestRunner.class)
public class ProductServiceTest {
    @Inject
    @Named(Constants.SERVICE_PRODUCT)
    ProductService productService;

    @Test
    public void testServiceCreation() {
        Gson gson = new GsonBuilder()
                .setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES)
                .create();

        RequestInterceptor requestInterceptor = new RequestInterceptor() {
            @Override
            public void intercept(RequestFacade request) {
                request.addQueryParam("api_key", "mykey");
            }
        };

        RestAdapter restAdapter = new RestAdapter.Builder()
                .setEndpoint("https://someendpoint.de/api/v1/")
                .setRequestInterceptor(requestInterceptor)
                .setConverter(new GsonConverter(gson))
                .build();

        ProductService service = restAdapter.create(ProductService.class);
        assertThat(service).isNotNull();
    }

    @Test
    public void testRetrieveProducts() {
        assertThat(productService).isNotNull();
    }
}

Now, for the question: Why doesn't injection work in the test class?

@johncarl81
Copy link
Owner

Injection doesn't work in this case because Transfuse didn't process the test class. This brings up an excellent idea though, what if we had an injector you could use for this sort of case? Something like this:

@RunWith(RobolectricGradleTestRunner.class)
@Injectable
public class ProductServiceTest {
    @Inject
    @Named(Constants.SERVICE_PRODUCT)
    ProductService productService;

    @Before
    public void setup(){
         TransfuseInjector.inject(this);
    }
    @Test
    public void testRetrieveProducts(){
        assertThat(productService).isNotNull();
    }
}

Thoughts?

In the mean time you can use Robolectric along with the generated classes to test injections (see the integration test example for details)

@ghost
Copy link
Author

ghost commented May 23, 2014

Ah, so that's the reason.
@Injectable sounds like a great idea :)

@johncarl81
Copy link
Owner

You could also write your injections manually. This is essentially what Transfuse would write for you:

@RunWith(RobolectricGradleTestRunner.class)
public class ProductServiceTest {

    ProductService productService;

    @Before
    public void setup(){
         productService = new MainModule().getProductService();
    }
    @Test
    public void testRetrieveProducts(){
        assertThat(productService).isNotNull();
    }
}

@johncarl81 johncarl81 added this to the 1.0.0 Release milestone Aug 24, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant