Bagaimana kita bisa mengakses konteks aplikasi di Robolectric?

112

Sebenarnya, saya perlu mendapat respons dari panggilan API, untuk itu saya memerlukannya Context.

pengguna1667968
sumber

Jawaban:

218

Memperbarui.

Cukup gunakan untuk versi 1.x dan 2.x:

Robolectric.application;

Dan untuk versi 3.x:

RuntimeEnvironment.application;

Dan untuk versi 4.x:

  • tambahkan ke build.gradlefile Anda :

    testImplementation 'androidx.test:core:1.0.0'
    
  • ambil konteksnya dengan:

    ApplicationProvider.getApplicationContext()
    
Eugen Martynov
sumber
11
Apakah Anda menempatkan @RunWith (RobolectricTestRunner.class) untuk pengujian Anda?
Eugen Martynov
4
Ya .. Saya menambahkan ... tapi tetap saja mengembalikan null
user1667968
1
Saya telah melakukan semua yang Anda sebutkan dan masih mendapatkan nol. Ada lagi yang mungkin saya lewatkan?
Moises Jimenez
13
Juga pastikan bahwa Anda tidak menggunakan RuntimeEnvironment.applicationkode statis (seperti metode yang dianotasi @BeforeClass) karena Robolectric mungkin tidak akan diinisialisasi pada saat itu dan nilainya akan seperti itu null.
sfera
1
Hal ini juga menyebabkan aplikasi berdarah di antara pengujian .. yang mungkin tidak diinginkan
Chris
26

Kamu bisa memakai

RuntimeEnvironment.application
rds
sumber
4
di RoboElectric 3.0, Roboelectric.application tidak ada lagi, jadi ini mungkin jawaban terbaik
kenyee
19

Gunakan ini:

Robolectric.application
Xian
sumber
16

Menambahkan

testImplementation "androidx.test:core-ktx:${deps.testrunner}"

Dan gunakan:

private val app = ApplicationProvider.getApplicationContext()
John
sumber
impor androidx.test.core.app.ApplicationProvider
luckyhandler
val appContext = ApplicationProvider.getApplicationContext <Context> ()
luckyhandler
2
Ini adalah jawaban yang benar dengan Robolectric terbaru. Metode lain yang disebutkan di sini tidak digunakan lagi atau dihapus.
Gabor
7

Untuk Robolectric 4.3 terbaru saat ini di tahun 2019 '

ShadowApplication.getInstance ()

`dan

Roboletric.application

keduanya dikecualikan. Jadi saya menggunakan

Context context = RuntimeEnvironment.systemContext;

untuk mendapatkan Konteks.

The_Martian
sumber
5

Untuk mendapatkan konteks aplikasi, Anda harus melakukan hal berikut:

  1. anotasi @RunWith (RobolectricTestRunner.class)
  2. RuntimeEnvironment.application.getApplicationContext ()
pengguna1390616
sumber
2

Ini berfungsi untuk saya dengan Robolectric 3.5.1: ShadowApplication.getInstance().applicationContext

Farrukh Najmi
sumber
Perhatikan bahwa sepertinya rilis 4.0 akan menghapus metode ini; lebih baik untuk tetap bersama RuntimeEnvironment.applicationatau RuntimeEnvironment.application.getApplicationContext()jika itu berhasil untuk Anda.
qix
2

Pada rilis 4.0-alpha-3 pada 21 Juli, mereka dihapus ShadowApplication.getApplicationContext() . Tetap gunakan RuntimeEnvironment.application.getApplicationContext()untuk pengujian apa pun yang dianotasi @RunWith(RobolectricTestRunner::class).

Selain itu, panduan mereka saat ini memiliki contoh mendapatkan resource string menggunakan:

final Context context = RuntimeEnvironment.application;

(Perhatikan bahwa javadocs untuk RuntimeEnvironmentdan ShadowApplicationsaat ini mencerminkan rilis non-alfa 3.x.)

qix
sumber
2

Pertama tambahkan yang berikut ini ke Anda build.gradle:

testImplementation 'androidx.test:core:1.2.0'

lalu gunakan:

ApplicationProvider.getApplicationContext() as Application

dougie
sumber
2

Dalam beberapa kasus, Anda mungkin memerlukan konteks aplikasi Anda, bukan konteks default Robolectris. Misalnya, jika Anda ingin mendapatkan nama paket Anda. Secara default, Robolectric akan mengembalikan org.robolectric.defaultnama paket Anda . Untuk mendapatkan nama paket asli Anda, lakukan hal berikut:

build.gradle

testImplementation 'org.robolectric:robolectric:4.2.1'

Kelas tes Anda:

@RunWith(RobolectricTestRunner.class)
@Config( manifest="AndroidManifest.xml")
public class FooTest {

@Test
public void fooTestWithPackageName(){
    Context context = ApplicationProvider.getApplicationContext();
    System.out.println("My Real Package Name: " + context.getPackageName());
}

}

Pastikan bahwa direktori Kerja Konfigurasi Run / Debug Anda disetel ke: $ MODULE_DIR $ masukkan deskripsi gambar di sini masukkan deskripsi gambar di sini

Kirill Karmazin
sumber
1

Ini lebih aman digunakan Robolectric.getShadowApplication()daripada menggunakan Robolectric.applicationsecara langsung.

drspaceboo
sumber
Tetapi bagaimana jika saya perlu mengakses beberapa properti kustom dari aplikasi kustom saya? Sepertinya saya tidak bisa mendapatkan objek sebenarnya dari aplikasi bayangan.
Denis Kniazhev
@DenisKniazhev Maaf saya tidak bisa menjawabnya untuk Anda. Tak lama setelah kami mulai menggunakan Robolectric, kami mulai menggunakan Travis sebagai CI kami, dan mereka tidak berfungsi dengan baik. Dugaan saya adalah Anda dapat mentransmisikannya ke aplikasi Anda atau Anda mungkin perlu membuat runner khusus untuk mendapatkan akses ke sana. Semoga sukses
drspaceboo
Terima kasih, untuk saat ini saya baru saja berpegang padaRobolectric.application
Denis Kniazhev
6
Robolectric.getShadowApplication () tidak tersedia
IgorGanapolsky
1

Setuju dengan jawaban @EugenMartynov dan @rds ....

Contoh cepat dapat ditemukan di Volley-Marshmallow-Release

di NetworkImageViewTest.java

// mNIV = new NetworkImageView(Robolectric.application); mNIV = new NetworkImageView(RuntimeEnvironment.application);

Tautan Volley tersedia https://android.googlesource.com/platform/frameworks/volley/+/marshmallow-release

Anda harus menambahkan dependensi dalam modul volley di android studio sebagai:

dependencies { testCompile 'junit:junit:4.12' testCompile 'org.mockito:mockito-core:1.10.19' testCompile 'org.robolectric:robolectric:3.1.2' }

Bhuro
sumber
1

Dalam kasus Anda, saya pikir Anda harus memperhatikan apa yang sebenarnya Anda uji. Kadang-kadang berlari ke masalah diuji kode atau kode yang tampaknya diuji adalah tanda bahwa mungkin kode Anda perlu refactored.

Untuk respons panggilan API, Anda mungkin tidak ingin menguji panggilan API itu sendiri. Mungkin tidak perlu untuk menguji apakah mungkin untuk mengirim / menerima informasi dari sembarang layanan web, tetapi kode Anda menangani dan memproses respons Anda dalam cara yang diharapkan.

Dalam hal ini mungkin lebih baik untuk memfaktor ulang kode yang Anda coba uji. Keluarkan respons parsing / penanganan ke kelas lain yang menerima sederhana Stringdan lakukan pengujian Anda pada kelas itu dengan memasukkan respons string sampel.

Ini kurang lebih mengikuti gagasan Single Responsibility and Dependency Inversion (The S dan D in SOLID )

grego
sumber
1

Oke, jadi saya tahu banyak orang lain yang mengatakan jawaban ini sebelumnya dan mungkin sudah ketinggalan zaman

    when(mockApplication.getApplicationContext()).thenReturn(RuntimeEnvironment.application);
    when(mockApplication.getFilesDir()).thenReturn(RuntimeEnvironment.application.getFilesDir());

    sharedPref = RuntimeEnvironment.application.getSharedPreferences(KEY_MY_PREF, Context.MODE_PRIVATE);
    sut = new BundleManagerImpl(mockApplication,
            processHtmlBundle, resultListener, sharedPref);

Saya mendapatkan null, karena when () part adalah SETELAH inisialisasi sut. Mungkin membantu beberapa dari Anda.

juga saya punya

@RunWith(CustomRobolectricTestRunner.class)
@Config(constants = BuildConfig.class)

di awal kelas

Juga

 when(mockApplication.getApplicationContext()).thenReturn(RuntimeEnvironment.application.getApplicationContext()); works
Karoly
sumber