1package com.xtremelabs.robolectric.matchers; 2 3import android.app.Service; 4import android.content.Context; 5import android.content.ContextWrapper; 6import android.content.Intent; 7import com.xtremelabs.robolectric.shadows.ShadowIntent; 8import org.hamcrest.Description; 9import org.junit.internal.matchers.TypeSafeMatcher; 10 11import java.util.Set; 12 13import static com.xtremelabs.robolectric.Robolectric.getShadowApplication; 14import static com.xtremelabs.robolectric.Robolectric.shadowOf; 15 16public class StartedServiceMatcher extends TypeSafeMatcher<Context> { 17 private final Intent expectedIntent; 18 19 private String message; 20 21 public StartedServiceMatcher(Intent expectedIntent) { 22 this.expectedIntent = expectedIntent; 23 } 24 25 public StartedServiceMatcher(String packageName, Class<? extends Service> expectedServiceClass) { 26 this(createIntent(packageName, expectedServiceClass)); 27 } 28 29 public StartedServiceMatcher(Class<? extends Service> expectedServiceClass) { 30 this(createIntent(expectedServiceClass)); 31 } 32 33 public StartedServiceMatcher(Class<? extends Service> expectedServiceClass, String expectedAction) { 34 this(createIntent(expectedServiceClass)); 35 36 expectedIntent.setAction(expectedAction); 37 } 38 39 /** 40 * Check if the class of the intent and the keys of the intent's extras match 41 * 42 * @param actualContext 43 * @return 44 */ 45 @Override 46 public boolean matchesSafely(Context actualContext) { 47 if (expectedIntent == null) { 48 message = "null intent (did you mean to expect null?)"; 49 return false; 50 } 51 52 String expected = expectedIntent.toString(); 53 message = "to start " + expected + ", but "; 54 55 Intent actualStartedIntent = shadowOf((ContextWrapper) actualContext).getNextStartedService(); 56 57 if (actualStartedIntent == null) { 58 message += "didn't start anything"; 59 return false; 60 } 61 62 ShadowIntent shadowIntent = shadowOf(actualStartedIntent); 63 64 //boolean intentsMatch = shadowOf(expectedIntent).realIntentEquals(shadowIntent); 65 // Test only that we are sending intent to the right service class 66 boolean intentsMatch = shadowOf(expectedIntent).getIntentClass().equals(shadowIntent.getIntentClass()); 67 if (!intentsMatch) { 68 message += "started " + actualStartedIntent; 69 } else { 70 // Test that both intent extras have the same keys 71 Set<String> keys = shadowIntent.getExtras().keySet(); 72 Set<String> expectedKeys = shadowOf(expectedIntent).getExtras().keySet(); 73 intentsMatch = keys.equals(expectedKeys); 74 if(!intentsMatch){ 75 message += "did not get the same extras keys"; 76 } 77 } 78 79 return intentsMatch; 80 } 81 82 @Override 83 public void describeTo(Description description) { 84 description.appendText(message); 85 } 86 87 public static Intent createIntent(Class<? extends Service> serviceClass, String extraKey, String extraValue) { 88 Intent intent = createIntent(serviceClass); 89 intent.putExtra(extraKey, extraValue); 90 return intent; 91 } 92 93 public static Intent createIntent(Class<? extends Service> serviceClass, String action) { 94 Intent intent = createIntent(serviceClass); 95 intent.setAction(action); 96 return intent; 97 } 98 99 public static Intent createIntent(Class<? extends Service> serviceClass) { 100 Package pack = serviceClass.getPackage(); 101 String packageName = "android.service"; 102 // getPackage is returning null when run from tests 103 if(pack != null) { 104 pack.getName(); 105 } 106 return createIntent(packageName, serviceClass); 107 } 108 109 public static Intent createIntent(String packageName, Class<? extends Service> serviceClass) { 110 Intent intent = new Intent(); 111 intent.setClassName(packageName, serviceClass.getName()); 112 intent.setClass(getShadowApplication().getApplicationContext(), serviceClass); 113 return intent; 114 } 115} 116