Android тесты: тушение модернизации с Mockito

в своем MainActivity у меня есть метод, называемый getAPI что возвращает OTBServiceWrapper. Используется для настройки дооснащения вызова API.

в своем MainActivityTest файл я пытаюсь заглушить new OTBService().getService() называем это getApi метод делает так, что я могу вернуть MockedOTBService который изменяет клиента на пользовательский, который возвращает json.

как есть, текущая реализация будет это MockedOTBService если бы мне пришлось поместить лесоруба в MockedOTBService но также падает через и вызывает реальный api, который не хочу я хочу в тесте.

я пытаюсь заглушить вызовы API Retrofit с помощью Mockito и return json. Кажется, я не могу понять, почему заглушка вызывается, но не тушит рассматриваемый метод.

Примечания:

  1. я использую ActivityInstrumentationTestCase2
  2. я запускаю только один тест
  3. если я добавлю verify(mockedOTBService, atLeastOnce()).getService(); is говорит, что он никогда не назывался.
  4. если я изменю when...thenReturn использовать mMainActivity = spy(getActivity()) нет изменений, и вызывается реальный API.

Вывод Logcat

Logger﹕ MockedOTBService was called // Mock is called
Logger﹕ Real OTBService was called // Real API is called
Logger﹕ MainActivity getAPI method class is "$Proxy1" // Mock is shown in MainActivity
Logger﹕ RealAPIResponse JSON Parsed ID: 266 // Real API response returned

Поток

MainActivity.onCreate () > OTBService.getService () > OTBServiceWrapper.createSearch(...)

пытается достичь в рамках тестов

MainActivity.onCreate () > MockedOTBService.getService() > OTBServiceWrapper.createSearch(...)

MainActivity.java

public class MainActivity extends Activity {
  private OTBServiceWrapper serviceWrapper;

  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    getApi().createSearch(...)
  }

  public OTBServiceWrapper getApi() {
    return new OTBService().getService();
  }
}

OTBService.java

public class OTBService {
  public OTBServiceWrapper getService() {
    RestAdapter restAdapter = new RestAdapter.Builder()
        .setEndpoint(Constants.API_URL)
        .build();

    return restAdapter.create(OTBServiceWrapper.class);
  }
}

OTBServiceWrapper.java

public interface OTBServiceWrapper {
  @POST(Constants.API_SEARCHES_POST_URL)
  void createSearch(@Body Request request, Callback<Request.Response> callback);
}

MainActivityTest.java

public class MainActivityTest extends ActivityInstrumentationTestCase2<MainActivity> {
  private OTBService mMockedOTBService;
  private MainActivity mMainActivity;
  private View mSearchButton;

  public MainActivityTest() { super(MainActivity.class); }

  @Override
  protected void setUp() throws Exception {
    super.setUp();

    setActivityInitialTouchMode(true);

    System.setProperty("dexmaker.dexcache", getInstrumentation().getTargetContext().getCacheDir().getPath());

    mMockedOTBService = mock(OTBService.class);
    when(mMockedOTBService.getService()).thenReturn(new MockedOTBService(getInstrumentation().getContext()).getService());

    mMainActivity = getActivity();

    mSearchButton = mMainActivity.findViewById(R.id.AbSearchButton);
    mYourHolidayButton = mMainActivity.findViewById(R.id.AbYourHolidayButton);
  }

  public void testButtonActions() {
    TouchUtils.clickView(this, mSearchButton);
    ...
  }
}

MockedOTBService.java

public class MockedOTBService {
  private Context context;

  public MockedOTBService(Context context) { this.context = context; }

  public OTBServiceWrapper getService() {
    RestAdapter restAdapter;

    restAdapter = new RestAdapter.Builder()
        .setClient(new LocalJsonClient(context))
        .setEndpoint(Constants.API_TEST_URL)
        .build();

    return restAdapter.create(OTBServiceWrapper.class);
  }
}

LocalJsonClient.java

@SuppressLint("DefaultLocale")
public class LocalJsonClient implements Client { ... }

построить.Gradle в

dependencies {
    androidTestCompile 'com.google.dexmaker:dexmaker:1.0'
    androidTestCompile 'com.google.dexmaker:dexmaker-mockito:1.0'
}

1 ответов


удалите необходимость в издевательстве над вашим запросом, разрешив действие установить службу.

в своем MainActivity создайте переменную класса и задатчик класса для службы. Он должен быть в области класса, чтобы предотвратить OnCreate метод вызывается до того, как вы установили службу на то, что вы хотите. Также создайте экземпляр getter, который устанавливает службу, если вы еще этого не сделали.

в тесте перед вызовом getActivity() установите службу, чтобы быть вашим макетом услуга. (Возможно, подумайте о перемещении этого на объект поддержки).

MainActivity.java

public class MainActivity extends Activity {
  private static OTBServiceWrapper serviceWrapper;

  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    getServiceWrapper.createSearch(...)
  }

  public OTBServiceWrapper getServiceWrapper() {
    if (serviceWrapper == null) {
      MainActivity.setServiceWrapper(new OTBService().getService());
    }

    return serviceWrapper;
  }

  public static void setServiceWrapper(OTBServiceWrapper serviceWrapper) {
    MainActivity.serviceWrapper = serviceWrapper;
  }
}

MainActivityTest.java

public class MainActivityTest extends ActivityInstrumentationTestCase2<MainActivity> {
  private MainActivity mMainActivity;

  public MainActivityTest() { super(MainActivity.class); }

  @Override
  protected void setUp() throws Exception {
    super.setUp();

    setActivityInitialTouchMode(true);

    MainActivity.setServiceWrapper(
      new MockedOTBService(getInstrumentation().getContext()).getService()
    );

    mMainActivity = getActivity();
  }
}