Help creating ShadowConnectivityManager

739 views
Skip to first unread message

Macarse

unread,
Nov 28, 2010, 7:44:24 PM11/28/10
to robol...@googlegroups.com
Hi,

In my app I have an SplashScreen and I want to check if the user has
internet before moving to the next Activity.
I am checking it using this model class:

public class ConnectionStatus implements IConnectionStatus {

private ConnectivityManager cm;

@Inject
public ConnectionStatus(ConnectivityManager cm) {
this.cm = cm;
}

public boolean isOnline() {
NetworkInfo netInfo = cm.getActiveNetworkInfo();
if (netInfo != null && netInfo.isConnectedOrConnecting()) {
return true;
}

return false;
}
}

Note: Roboguice knows how to inject a SystemService.


1) Questions related to the creation of the Shadow:

I wanted to create a shadow of ConnectivityManager.
This is what I did so far:

@Implements(NetworkInfo.class)
public class ShadowNetworkInfo {

private boolean isConnected = false;

@Implementation
public boolean isConnectedOrConnecting() {
return isConnected;
}

/* This method is used to set the status of the internet
connection manually */
public void setConnectionStatus(boolean isConnected) {
this.isConnected = isConnected;
}
}

a) It's ok to have a method there to set the status manually?

@Implements(ConnectivityManager.class)
public class ShadowConnectivityManager {

@Implementation
public NetworkInfo getActiveNetworkInfo() {
/* b) Here I need to return a shadow of NetworkInfo. I don't
know if this is the correct way of doing it */
NetworkInfo ni = Robolectric.newInstanceOf(NetworkInfo.class);
return ni;
}
}

c)
After coding both classes I should add them to
public static List<Class<?>> getDefaultShadowClasses() {
return Arrays.asList( bla bla....

in Robolectric.class right?


2) Question related to the test itself.

I need an Android context to do:
ConnectivityManager cm = (ConnectivityManager​)
context.getSystemService(Context.CONNECTIVITY_SERVICE);

a)
Is there a better way to do it than doing:

private SplashActivity context;

@Before
public void setUp() {
context = new SplashActivity();
}

Which is the correct way of getting a context?

Christian mentioned in one of his tweets:
@mgv we override RobolectricTestHelper.prepareTest() to Guice-inject
onto the test class, works great!

Can you explain what he's doing there? I guess with that I can do
injection in the test itself but I am not completely sure how.

b)
In the test I need to use ShadowNetworkInfo's setConnectionStatus() method.
It should be something like this:

ConnectivityManager cm = (ConnectivityManager​)
context.getSystemService(Context.CONNECTIVITY_SERVICE);
ShadowNetworkInfo shadow = cm.getActiveNetworkInfo();
shadow.setConnectionStatus(true);

but I can't cast there. What should I do?


Thanks for reading! :)

Christian Williams

unread,
Nov 29, 2010, 10:18:45 AM11/29/10
to robol...@googlegroups.com
1a) Yep, that sounds right!
1b) Yes, since NetworkInfo doesn't have a public constructor, use Robolectric.newInstance(). If it did have a public (or protected) constructor, you could just create a new one the regular way.
1c) Yes, if you want to contribute your shadows back to Robolectric (and please do!). If not, you can bind the shadow class using Robolectric.bindShadowClass().

2a) That's fine. You can also use the current Application instance (Robolectric.application), which is itself a context.
2b) This is from memory, so probably not exactly correct:

public class XxxTestRunner extends RobolectricTestRunner {
  public CustomTestRunner(Class testClass) throws InitializationError {
  
  super(testClass);
  }

  @Override protected Application createApplication() {
      return new TestXxxApplication();
  }

  @Override public void prepareTest(Object test) {
    ((GuiceApplication) Robolectric.application).getInjector().inject(test);
  }
}

2b) Then in your test, you just @Inject whatever you need:

@RunWith(XxxTestRunner.class)
public class XxxTest extends RobolectricTestRunner {
  @Inject SplashActivity splashActivity;
  @Inject ConnectivityManager connectivityManager;

  @Before
  public void setUp() {
    shadowOf(cm.getActiveNetworkInfo()).setConnectionStatus(true);
  }
}

You might consider making the ShadowNetworkInfo.isConnected field default to true though, seems like the more common case.

Hope that helps!

--Xian

Macarse

unread,
Dec 1, 2010, 9:03:52 AM12/1/10
to robol...@googlegroups.com
Ok work completed.
https://github.com/pivotal/robolectric/pull/11

Chris: Thanks for the feedback!

Reply all
Reply to author
Forward
0 new messages