1

I am using Robolectric and trying to create a Shadow object of GoogleApiClient but unsuccessfully. The methods from the Shadow class are never called. The GoogleApiClient is interface - could that be a problem? Is there any way how to 'shadow' the GoogleApiClient interface (or simulate GoogleApiClient in test)?

Implementation:

@Implements(GoogleApiClient.class)
public class ShadowGoogleApiClient {

public void __constructor__ (){
    System.out.println("__constructor____constructor__");
}

@Implementation
void connect() {
    System.out.println("connectconnectconnect");
}

@Implementation
boolean isConnected() {
    System.out.println("isConnectedisConnected");
    return false;
}

@Implementation
boolean isConnecting() {
    System.out.println("isConnectingisConnecting");
    return false;
}

}

and I've defined the Shadow class in my test:

@Config(shadows = {ShadowGoogleApiClient.class},
    constants = BuildConfig.class)
@RunWith(CustomRobolectricRunner.class)
public class ApiTest {
 ...
}
Zis
  • 162
  • 16
  • 1
    You must register your class for shadowing. See http://stackoverflow.com/questions/29629786/robolectric-shadow-not-working – nenick Sep 19 '15 at 05:18
  • Actually, it is still not working. I added the class (GoogleApiClient) to the InstrumentationConfiguration.Builder but with no changes. – Zis Sep 21 '15 at 10:51
  • GoogleApiClient is an interface. Not sure but it make sense that you can only shadow concrete classes. The real implementing class should be shown when you debug the app. You can shadow classes which aren't accessible by using the className property from @Implements – nenick Sep 21 '15 at 14:12
  • @nenick I think you are right. I have tested that hypothesis and it needs to be concrete class. The problem is that the concrete class of GoogleApiClient has a package private visibility and I cannot 'shadow' it (and its name is something like 'com.google.android.gms.common.api.c' which is decompiled name from the lib). – Zis Sep 21 '15 at 15:23
  • You can shadow "package private" classes just by writing the full qualified class name (package.ClassName). See className property from @Implements. When com.google.android.gms.common.api.c is stable, then use it. Does this come from just showing implementation classes or from debug? Maybe there you get a different classname – nenick Sep 21 '15 at 16:05
  • I have something like `GoogleApiClient apiClient = new GoogleApiClient.Builder(context);` then I called `apiClient.getClass(). getCanonicalName();` which returns `com.google.android.gms.common.api.c`. When I tried to use that full class name, then it says the class does not exist (in compile time). Think I run it in a debug mode (running gradle test task). Actually, looing into prop className from @Implements - so I'll try to define that class as a string and see what happens. – Zis Sep 21 '15 at 17:19
  • What are you testing? Do you want to force some connection result? – Steve C Sep 21 '15 at 18:12
  • @SteveC Yes. We have implementation based on each state of GoogleApiClient - connected/disconnected/connecting/unavailable. – Zis Sep 22 '15 at 09:22
  • @Zis did you solve it? Instead of shadowing the `GoogleApiClient` you can try to shadow the `GoogleApiClient.Builder(context).build()` method and return your own GoogleApiClient instance/mock – nenick Nov 08 '15 at 09:49

1 Answers1

0

Have you tried to use Mockito to mock the implementation of the GoogleApiClient?

doAnswer(new Answer() {
            @Override
            public Object answer(InvocationOnMock invocation) throws Throwable {
                myCallback.onConnected();
                return null;
            }
        }).when(mGoogleApiClient).connect();
Steve C
  • 1,034
  • 10
  • 12