Làm cách nào chúng ta có thể truy cập ngữ cảnh của một ứng dụng trong Robolectric?


112

Trên thực tế, tôi cần nhận phản hồi của một lệnh gọi API, cho điều đó tôi yêu cầu Context.

Câu trả lời:


218

Cập nhật.

Chỉ cần sử dụng cho phiên bản 1.x và 2.x:

Robolectric.application;

Và đối với phiên bản 3.x:

RuntimeEnvironment.application;

Và đối với phiên bản 4.x:

  • thêm vào build.gradletệp của bạn :

    testImplementation 'androidx.test:core:1.0.0'
    
  • truy xuất ngữ cảnh với:

    ApplicationProvider.getApplicationContext()
    

11
Bạn có đặt @RunWith (RobolectricTestRunner.class) cho các bài kiểm tra của mình không?
Eugen Martynov

4
Vâng .. Tôi thêm ... nhưng nó vẫn trả về null
user1667968

1
Tôi đã làm tất cả những gì bạn đã đề cập và vẫn nhận được giá trị không. Tôi còn thiếu gì nữa không?
Moises Jimenez

13
Ngoài ra, hãy đảm bảo rằng bạn không sử dụng RuntimeEnvironment.applicationmã tĩnh (như các phương thức được chú thích bằng @BeforeClass) vì Robolectric có thể sẽ không được khởi tạo tại thời điểm đó và giá trị sẽ là null.
sfera

1
Ngoài ra, điều này khiến ứng dụng bị chảy máu giữa các lần kiểm tra .. có thể không mong muốn
Chris

26

Bạn có thể dùng

RuntimeEnvironment.application

4
trong RoboElectric 3.0, Roboelectric.application không còn tồn tại, vì vậy đây có lẽ là câu trả lời tốt nhất
kenyee


16

Thêm vào

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

Và sử dụng:

private val app = ApplicationProvider.getApplicationContext()

import androidx.test.core.app.ApplicationProvider
luckyhandler

val appContext = ApplicationProvider.getApplicationContext <Context> ()
luckyhandler

2
Đây là câu trả lời chính xác với Robolectric mới nhất. Các phương pháp khác được đề cập ở đây không được chấp nhận hoặc bị loại bỏ.
Gabor

7

Đối với Robolectric 4.3 mới nhất kể từ bây giờ vào năm 2019 '

ShadowApplication.getInstance ()

`và

Roboletric.application

cả hai đều bị miêu tả. Vì vậy, tôi đang sử dụng

Context context = RuntimeEnvironment.systemContext;

để có được Ngữ cảnh.


5

Để có được ngữ cảnh ứng dụng, bạn phải làm như sau:

  1. chú thích @RunWith (RobolectricTestRunner.class)
  2. RuntimeEnosystem.application.getApplicationContext ()

2

Điều này phù hợp với tôi với Robolectric 3.5.1: ShadowApplication.getInstance().applicationContext


Lưu ý rằng có vẻ như bản phát hành 4.0 sẽ loại bỏ phương pháp này; tốt hơn để gắn bó với RuntimeEnvironment.applicationhoặc RuntimeEnvironment.application.getApplicationContext()nếu nó phù hợp với bạn.
qix

2

Kể từ bản phát hành 4.0-alpha-3 vào ngày 21 tháng 7, họ đã xóa ShadowApplication.getApplicationContext() . Gắn bó với RuntimeEnvironment.application.getApplicationContext()bất kỳ bài kiểm tra nào được chú thích @RunWith(RobolectricTestRunner::class).

Ngoài ra, hướng dẫn hiện tại của họ có một ví dụ về việc lấy tài nguyên chuỗi bằng cách sử dụng:

final Context context = RuntimeEnvironment.application;

(Lưu ý rằng javadocs cho RuntimeEnvironmentShadowApplicationhiện đang phản ánh bản phát hành 3.x không phải alpha.)


2

Trước tiên, hãy thêm phần sau vào của bạn build.gradle:

testImplementation 'androidx.test:core:1.2.0'

sau đó sử dụng:

ApplicationProvider.getApplicationContext() as Application


2

Trong một số trường hợp, bạn có thể cần ngữ cảnh của ứng dụng thay vì ngữ cảnh mặc định của Robolectris. Ví dụ, nếu bạn muốn lấy tên gói của mình. Theo mặc định, Robolectric sẽ trả về org.robolectric.defaulttên gói cho bạn . Để lấy tên gói thực của bạn, hãy làm như sau:

build.gradle

testImplementation 'org.robolectric:robolectric:4.2.1'

Lớp kiểm tra của bạn:

@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());
}

}

Đảm bảo rằng trong thư mục Run / Debug Configurations Working được đặt thành: $ MODULE_DIR $ nhập mô tả hình ảnh ở đây nhập mô tả hình ảnh ở đây


1

Sẽ an toàn hơn khi sử dụng Robolectric.getShadowApplication()thay vì sử dụng Robolectric.applicationtrực tiếp.


Nhưng nếu tôi cần truy cập một số thuộc tính tùy chỉnh của ứng dụng tùy chỉnh của mình thì sao? Có vẻ như tôi không thể lấy đối tượng thực từ ứng dụng bóng.
Denis Kniazhev

@DenisKniazhev Xin lỗi, tôi không thể trả lời cho bạn. Ngay sau khi chúng tôi bắt đầu sử dụng Robolectric, chúng tôi bắt đầu sử dụng Travis làm CI và chúng không hoạt động tốt. Tôi đoán là bạn có thể truyền nó vào ứng dụng của mình hoặc bạn có thể cần tạo một trình chạy tùy chỉnh để có quyền truy cập vào ứng dụng theo cách đó. Best of luck
drspaceboo

Cảm ơn, bây giờ tôi vừa bị mắc kẹt đếnRobolectric.application
Denis Kniazhev

6
Robolectric.getShadowApplication () là không có sẵn
IgorGanapolsky

1

Đồng ý với câu trả lời của @EugenMartynov và @rds ....

Một ví dụ nhanh có thể được tìm thấy tại Volley-Marshmallow-Release

trong NetworkImageViewTest.java

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

Liên kết Volley có sẵn https://android.googlesource.com/platform/frameworks/volley/+/marshmallow-release

bạn phải thêm các phần phụ thuộc vào mô-đun volley trong studio android như:

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


1

Trong trường hợp của bạn, tôi nghĩ bạn nên lưu ý đến những gì bạn đang thực sự thử nghiệm. Đôi khi gặp phải vấn đề về mã không thể kiểm tra được hoặc mã dường như không thể kiểm tra được là một dấu hiệu cho thấy có thể mã của bạn cần được cấu trúc lại.

Đối với phản hồi cuộc gọi API, bạn có thể không muốn kiểm tra chính lệnh gọi API. Có thể không cần thiết phải kiểm tra xem có thể gửi / nhận thông tin từ bất kỳ dịch vụ web tùy ý nào hay không, mà là mã của bạn xử lý và xử lý phản hồi của bạn trong một trang viên dự kiến.

Trong trường hợp đó, tốt hơn là nên cấu trúc lại mã mà bạn đang cố gắng kiểm tra. Phân tích cú pháp / xử lý phản hồi cho một lớp khác chấp nhận một lớp đơn giản Stringvà thực hiện thử nghiệm của bạn trên lớp đó bằng cách đưa vào các phản hồi chuỗi mẫu.

Điều này ít nhiều tuân theo các ý tưởng về Đảo ngược trách nhiệm đơn lẻPhụ thuộc ( SD trong SOLID )


1

Được rồi, tôi biết nhiều người khác đã nói câu trả lời này trước đây và có thể đã lỗi thời

    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);

Tôi nhận được null, vì phần when () là SAU khi khởi tạo sut. Nó có thể giúp một số bạn.

tôi cũng có

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

vào đầu buổi học

Cũng thế

 when(mockApplication.getApplicationContext()).thenReturn(RuntimeEnvironment.application.getApplicationContext()); works
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.