package org.robolectric; import android.os.Build; import javax.annotation.Nonnull; import org.junit.Before; import org.junit.Ignore; import org.junit.Test; import org.junit.runner.Description; import org.junit.runner.notification.Failure; import org.junit.runner.notification.RunListener; import org.junit.runner.notification.RunNotifier; import org.junit.runners.model.InitializationError; import org.robolectric.RobolectricTestRunner.RobolectricFrameworkMethod; import org.robolectric.android.internal.ParallelUniverse; import org.robolectric.annotation.Config; import org.robolectric.internal.ParallelUniverseInterface; import org.robolectric.internal.SdkConfig; import org.robolectric.internal.SdkEnvironment; import org.robolectric.manifest.AndroidManifest; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.List; import java.util.Properties; import static android.os.Build.VERSION_CODES.JELLY_BEAN; import static java.util.Arrays.asList; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.Assert.fail; import static org.mockito.Mockito.mock; import static org.robolectric.util.ReflectionHelpers.callConstructor; public class RobolectricTestRunnerTest { private RunNotifier notifier; private List<String> events; @Before public void setUp() throws Exception { notifier = new RunNotifier(); events = new ArrayList<>(); notifier.addListener(new RunListener() { @Override public void testIgnored(Description description) throws Exception { events.add("ignored: " + description.getDisplayName()); } @Override public void testFailure(Failure failure) throws Exception { events.add("failure: " + failure.getMessage()); } }); } @Test public void ignoredTestCanSpecifyUnsupportedSdkWithoutExploding() throws Exception { RobolectricTestRunner runner = new MyRobolectricTestRunner(TestWithOldSdk.class); runner.run(notifier); assertThat(events).containsOnly( "failure: Robolectric does not support API level 11.", "ignored: ignoredOldSdkMethod(org.robolectric.RobolectricTestRunnerTest$TestWithOldSdk)" ); } @Test public void failureInResetterDoesntBreakAllTests() throws Exception { RobolectricTestRunner runner = new MyRobolectricTestRunner(TestWithTwoMethods.class) { @Override ParallelUniverseInterface getHooksInterface(SdkEnvironment sdkEnvironment) { Class<? extends ParallelUniverseInterface> clazz = sdkEnvironment.bootstrappedClass(MyParallelUniverse.class); return callConstructor(clazz); } }; runner.run(notifier); assertThat(events).containsExactly( "failure: fake error in resetStaticState", "failure: fake error in resetStaticState" ); } @Test public void equalityOfRobolectricFrameworkMethod() throws Exception { Method method = TestWithTwoMethods.class.getMethod("first"); RobolectricFrameworkMethod rfm16 = new RobolectricFrameworkMethod(method, mock(AndroidManifest.class), new SdkConfig(16), mock(Config.class)); RobolectricFrameworkMethod rfm17 = new RobolectricFrameworkMethod(method, mock(AndroidManifest.class), new SdkConfig(17), mock(Config.class)); RobolectricFrameworkMethod rfm16b = new RobolectricFrameworkMethod(method, mock(AndroidManifest.class), new SdkConfig(16), mock(Config.class)); assertThat(rfm16).isEqualTo(rfm16); assertThat(rfm16).isNotEqualTo(rfm17); assertThat(rfm16).isEqualTo(rfm16b); assertThat(rfm16.hashCode()).isEqualTo((rfm16b.hashCode())); } ///////////////////////////// public static class MyParallelUniverse extends ParallelUniverse { @Override public void resetStaticState(Config config) { throw new RuntimeException("fake error in resetStaticState"); } } @Ignore public static class TestWithOldSdk { @Config(sdk = Build.VERSION_CODES.HONEYCOMB) @Test public void oldSdkMethod() throws Exception { fail("I should not be run!"); } @Ignore("This test shouldn't run, and shouldn't cause the test runner to fail") @Config(sdk = Build.VERSION_CODES.HONEYCOMB) @Test public void ignoredOldSdkMethod() throws Exception { fail("I should not be run!"); } } @Ignore public static class TestWithTwoMethods { @Test public void first() throws Exception { } @Test public void second() throws Exception { } } private static class MyRobolectricTestRunner extends RobolectricTestRunner { public MyRobolectricTestRunner(Class<?> testClass) throws InitializationError { super(testClass); } @Nonnull @Override protected SdkPicker createSdkPicker() { return new SdkPicker(asList(new SdkConfig(JELLY_BEAN)), new Properties()); } } }