2016-06-07 7 views
4

В настоящее время я унаследовал приложение для Android, которое имеет нулевое покрытие кода, и моя первая работа - получить некоторые модульные тесты, написанные для него. Поэтому я решил использовать его как возможность изучить Robolectric.Robolectric - приложение имеет синглтоны в настройке, вызывая проблемы с тестами

Однако я запускаю начальные проблемы, получая два простых теста-пустышки для запуска.

Вот мой код в моем тестовом файле:

@Config(constants = BuildConfig.class) 
@RunWith(RobolectricGradleTestRunner.class) 
public class SplashActivityTest { 

private SplashActivity activity; 

// @Before => JUnit 4 annotation that specifies this method should run before each test is run 
// Useful to do setup for objects that are needed in the test 
@Before 
public void setup() { 
    // Convenience method to run SplashActivity through the Activity Lifecycle methods: 
    // onCreate(...) => onStart() => onPostCreate(...) => onResume() 
    activity = Robolectric.setupActivity(SplashActivity.class); 
} 

// @Test => JUnit 4 annotation specifying this is a test to be run 
// Checking that the UI gets setup correctly 
@Test 
public void dummy() { 
    String test = "POP!"; 

    assertTrue("POP!", 
      test.equals("POP!")); 
} 

@Test 
public void dummyTwo() { 

    String test = "POP!!"; 

    assertTrue("POP!!", 
      test.equals("POP!!")); 
} 

} 

Проблема заключается деятельность расширяет другой класс с именем baseactivity и в этом классе используется класс пользовательских приложений.

В этом классе пользовательских приложений Пикассо создается как Singleton, используя следующий код:

picasso = new Picasso.Builder(getApplicationContext()).downloader(new OkHttpDownloader(picassoClient)).build(); 
    Picasso.setSingletonInstance(picasso); 

Когда я запускаю тесты, которые я получаю следующее сообщение об ошибке:

java.lang.IllegalStateException: Singleton instance already exists. at com.squareup.picasso.Picasso.setSingletonInstance(Picasso.java:677)

Так это выглядит как класс приложения создается дважды, один раз для каждого теста, так как с одним тестом он работает нормально. Итак, я предполагаю, что мой образец для тестирования здесь неправильный? Может ли кто-нибудь помочь мне с правильным шаблоном? Как и в случае с модульным тестом, я хочу просто проверить ограниченную функциональность, поэтому я не уверен, что я делаю правильно.

EDIT: Я попытался настроить класс «mock» и получить Robolectric для его использования, но он все еще, кажется, использует настоящий класс приложения.

Так в тестовом/Java У меня есть следующий класс:

public class TestMyApplication extends MyApplication 
     implements TestLifecycleApplication { 

    @Override 
    public void onCreate() { 
     super.onCreate(); 
     initPicasso(); 
    } 

    @Override 
    protected void initPicasso() { 
     //nothing to do 
    } 

    @Override public void beforeTest(Method method) { 
    } 

    @Override public void prepareTest(Object test) { 
    } 

    @Override public void afterTest(Method method) { 
    } 
} 

Как вы можете видеть, что расширяет класс MyApplication, который находится в моем главном приложении, и я также добавил @Override методу initPicasso попробовать чтобы остановить его вызов, однако, когда я запускаю свои тесты, я до сих пор получаю ошибку, когда Picasso Singleton устанавливается во второй раз для второго теста.

Итак, когда я запускаю свой тестовый класс, он по-прежнему входит в класс Application в моем основном приложении, почему Robolectric делает это, когда модульные тесты должны быть ограничены по охвату?

Я также попытался это:

@Config(constants = BuildConfig.class, application = TestMyApplication.class) 

Но когда я пытаюсь это и запустить тестовый класс я получаю ошибку о том, что не может найти TestMyApplication, поэтому его разрывают мои волосы вопрос, почему Robolectric не будет использовать мой классный класс приложений.

+1

http://stackoverflow.com/questions/36969659/robolectric-3- with-fabric-crashlytics/36980405 # 36980405 –

+0

@EugenMartynov - Я пробовал этот подход, следуя этому - http://robolectric.org/custom-test-runner/ - и у меня все еще такая же проблема, как и ее игнорирование Класс TestApplication –

+1

, если вы попытались использовать этот подход, то что вы изменили? Он должен создавать приложение для каждого теста. Единичные тесты должны быть независимыми и повторяемыми. –

ответ

4

Чтобы заставить его работать, мне пришлось создать следующий класс, который расширяет RobolectricGradleTestRunner и заставляет его использовать класс TestMyApplication.

public class TestRunner extends RobolectricGradleTestRunner { 

    public TestRunner(final Class<?> testClass) throws InitializationError { 
     super(testClass); 
    } 

    @Override 
    protected Class<? extends TestLifecycle> getTestLifecycleClass() { 
     return MyTestLifecycle.class; 
    } 

    public static class MyTestLifecycle extends DefaultTestLifecycle { 
     @Override 
     public Application createApplication(final Method method, final AndroidManifest appManifest, final Config appConfig) { 
      // run tests under our TestApplication 
      return new TestMyApplication(); 
     } 
    } 

} 

Тогда в классе TestMyApplication мне пришлось переопределить метод initPicasso:

@Override protected void initPicasso(){ 
     //do nothing 
    } 

Только после того, как делать это сделал Robolectric наконец пропустить initPicasso в главном классе MyApplication.java.

+2

он все равно должен работать из коробки :) Если вы можете использовать код, я могу его исправить, по крайней мере, я хочу :) –

+0

Я попытаюсь собрать образец его, когда я получу шанс и отправлю его для вас я не могу поделиться этим конкретным кодом. –

+0

Пожалуйста, сохраняйте ароматы и отразите в нем изменения идентификатора приложения –

2

В Robolectric 3.4.2, использовать пользовательский класс приложений в тестах работает:

public class MyApplication extends Application { 

    protected void initPicasso() { 
     // do Picasso initialization 
    } 

} 

public class TestMyApplication extends MyApplication { 

    @Override 
    protected void initPicasso() { 
     //nothing to do 
    } 

} 

Просто добавьте аннотацию Config в тестовых классах:

@Config(constants = BuildConfig.class, application = TestMyApplication.class)