Модульное тестирование Модифицированные вызовы, когда сервис вводится с помощью Dagger 2 - PullRequest
0 голосов
/ 14 октября 2018

Я использую Dagger 2, чтобы предоставить все свои классы в приложении для Android.Я хочу провести модульное тестирование своего класса репозитория, в котором есть служба Retrofit в конструкторе.

class MainRepository(private val service: ImageService) {

fun download(username: String, liveData: MutableLiveData<ImageDownloadResult>) {
    service.downloadImage(username).enqueue(object : Callback<ImageResponse> {
        override fun onFailure(call: Call<ImageResponse>, t: Throwable) {
            liveData.value = DownloadFailed(t)
        }

        override fun onResponse(call: Call<ImageResponse>, response: Response<ImageResponse>) {
            if (response.isSuccessful) {
                response.body()?.let {
                    liveData.value = DownloadSuccessful(it.image)
                }
            } else {
                liveData.value = DownloadFailed(
                    when (response.code()) {
                        401 -> Unauthorized()
                        403 -> Forbidden()
                        404 -> NotFound()
                        in 500..599 -> InternalServerError()
                        else -> General()
                    }
                )
            }
        }
    })
}

}

Класс сетевого модуля предоставляет службу следующим образом:

@Provides
@Singleton
fun provideImageService(gson: Gson, okHttpClient: OkHttpClient): ImageService {
    return Retrofit.Builder()
        .addConverterFactory(GsonConverterFactory.create(gson))
        .baseUrl(mBaseUrl)
        .client(okHttpClient)
        .build()
        .create(ImageService::class.java)
}

Я пытаюсь использовать Mockito для насмешки над классами, но я получаю исключение NullPointerException в методе download.

public class MainRepositoryTest {

@Rule
public MockitoRule mockitoRule = MockitoJUnit.rule();
@InjectMocks
ImageService service;

@Before
public void setup() {
    MockitoAnnotations.initMocks(this);
}

@Test
public void testImageDownload() {
    MutableLiveData<ImageDownloadResult> liveData = new MutableLiveData<>();
    Response<ImageResponse> response = null;
    try {
        response = service.downloadImage("test").execute();
        assertEquals(response.code(), 200);
    } catch (IOException e) {
        e.printStackTrace();
    }
}

}

Пожалуйста, научите меня внедрять сервис в тест, чтобычто я могу позвонить по Http звонки туда.Спасибо!

1 Ответ

0 голосов
/ 21 октября 2018

Я думаю, что вы запутываете некоторые биты здесь.В тесте вы, похоже, тестируете сервис, а не репозиторий.Служба должна быть смоделирована для того, чтобы действительно что-то вернуть, а не ноль.

Давайте начнем с настройки теста.Вам нужно будет объявить макеты и то, что вы тестируете

public class MainRepositoryTest {

  @Rule
  public MockitoRule mockitoRule = MockitoJUnit.rule();
  @Mock
  ImageService service;
  @InjectMocks
  MainRepository repository;

   //...
 }

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

Так что теперь вам нужно будет настроить его для каждого случая, который вы хотите протестировать.Скажем, вы хотите проверить успешный ответ:

@Test
public void testSuccess (){
    when(service.downloadImage("test")).theReturn(<successful response>);

     repository.download("test", <mutable live data>);

     // Now assert something about the live data
}

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

Что касается кинжала, то здорово, что вы используете внедрение зависимостей.Однако в тестах обычно не вводят зависимости с помощью кинжала.Здесь достаточно использовать аннотацию mockito.

...