เราจะเข้าถึงบริบทของแอปพลิเคชันใน Robolectric ได้อย่างไร?


112

อันที่จริงผมจำเป็นต้องได้รับการตอบสนองของการเรียก API Contextสำหรับที่ฉันจำเป็นต้องใช้

คำตอบ:


218

อัปเดต.

เพียงใช้สำหรับเวอร์ชัน 1.x และ 2.x:

Robolectric.application;

และสำหรับเวอร์ชัน 3.x:

RuntimeEnvironment.application;

และสำหรับเวอร์ชัน 4.x:

  • เพิ่มในbuild.gradleไฟล์ของคุณ:

    testImplementation 'androidx.test:core:1.0.0'
    
  • ดึงบริบทด้วย:

    ApplicationProvider.getApplicationContext()
    

11
คุณใส่ @RunWith (RobolectricTestRunner.class) สำหรับการทดสอบของคุณหรือไม่
Eugen Martynov

4
ใช่ .. ฉันเพิ่มแล้ว ... แต่ก็ยังคืนค่า null
user1667968

1
ฉันได้ทำสิ่งที่คุณพูดถึงทั้งหมดแล้วและยังคงได้รับค่าว่าง มีอะไรอีกบ้างที่ฉันอาจขาดหายไป?
Moises Jimenez

13
ยังให้แน่ใจว่าคุณไม่ได้ใช้RuntimeEnvironment.applicationในรหัสคงที่ (เช่นวิธีการกำกับด้วย@BeforeClass) เป็น Robolectric nullอาจจะไม่สามารถเริ่มต้นที่จุดนั้นและความคุ้มค่าที่จะเป็น
sfera

1
นอกจากนี้ยังทำให้แอปพลิเคชันมีเลือดออกระหว่างการทดสอบ .. ซึ่งอาจไม่เป็นที่ต้องการ
Chris

26

คุณสามารถใช้ได้

RuntimeEnvironment.application

4
ใน RoboElectric 3.0, Roboelectric.application ไม่มีแล้วดังนั้นนี่อาจเป็นคำตอบที่ดีที่สุด
kenyee


16

เพิ่ม

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

และใช้:

private val app = ApplicationProvider.getApplicationContext()

นำเข้า androidx.test.core.app.ApplicationProvider
luckyhandler

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

2
นี่คือคำตอบที่ถูกต้องสำหรับ Robolectric รุ่นล่าสุด วิธีการอื่น ๆ ที่กล่าวถึงนี้ถูกเลิกใช้หรือถูกลบออก
Gabor

7

สำหรับ Robolectric 4.3 ล่าสุด ณ ตอนนี้ในปี 2019 "

ShadowApplication.getInstance ()

`และ

Roboletric.application

ถูกกีดกันทั้งคู่ ดังนั้นฉันใช้

Context context = RuntimeEnvironment.systemContext;

เพื่อรับบริบท


5

ในการรับบริบทแอปพลิเคชันคุณต้องทำสิ่งต่อไปนี้:

  1. ใส่คำอธิบายประกอบ @RunWith (RobolectricTestRunner.class)
  2. RuntimeEnvironment.application.getApplicationContext ()

2

สิ่งนี้ใช้ได้กับฉันกับ Robolectric 3.5.1: ShadowApplication.getInstance().applicationContext


โปรดทราบว่าดูเหมือนว่ารุ่น 4.0 จะลบวิธีนี้ออกไป ดีกว่าที่จะติดRuntimeEnvironment.applicationหรือ RuntimeEnvironment.application.getApplicationContext()ถ้ามันทำงานให้คุณ
qix

2

ในฐานะของการเปิดตัว 4.0-alpha-3ในวันที่ 21 กรกฏาคมที่พวกเขาเอาออก ShadowApplication.getApplicationContext()Stick ที่มีRuntimeEnvironment.application.getApplicationContext()สำหรับการทดสอบข้อเขียนใด ๆ @RunWith(RobolectricTestRunner::class)กับ

นอกจากนี้คู่มือปัจจุบันยังมีตัวอย่างของการรับทรัพยากรสตริงโดยใช้:

final Context context = RuntimeEnvironment.application;

(โปรดทราบว่า javadocs สำหรับRuntimeEnvironmentและShadowApplicationปัจจุบันสะท้อนถึงรุ่นที่ไม่ใช่ alpha 3.x)


2

ขั้นแรกให้เพิ่มสิ่งต่อไปนี้ในของคุณbuild.gradle:

testImplementation 'androidx.test:core:1.2.0'

จากนั้นใช้:

ApplicationProvider.getApplicationContext() as Application


2

ในบางกรณีคุณอาจต้องใช้บริบทของแอปแทนบริบทเริ่มต้นของ Robolectris ตัวอย่างเช่นหากคุณต้องการรับชื่อแพ็กเกจของคุณ ตามค่าเริ่มต้น Robolectric จะส่งคืนorg.robolectric.defaultชื่อแพ็คเกจให้คุณ ในการรับชื่อแพ็กเกจจริงของคุณให้ทำดังต่อไปนี้:

build.gradle

testImplementation 'org.robolectric:robolectric:4.2.1'

ชั้นทดสอบของคุณ:

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

}

ตรวจสอบให้แน่ใจว่าในไดเร็กทอรี Run / Debug Configurations Working ของคุณถูกตั้งค่าเป็น: $ MODULE_DIR $ ใส่คำอธิบายภาพที่นี่ ใส่คำอธิบายภาพที่นี่


1

ปลอดภัยกว่าที่จะใช้Robolectric.getShadowApplication()แทนการใช้Robolectric.applicationโดยตรง


แต่ถ้าฉันต้องการเข้าถึงคุณสมบัติที่กำหนดเองบางอย่างของแอปพลิเคชันที่กำหนดเองของฉันล่ะ? ดูเหมือนว่าฉันไม่สามารถรับวัตถุจริงจากแอปพลิเคชันเงาได้
Denis Kniazhev

@DenisKniazhev ขอโทษที่ฉันไม่สามารถตอบให้คุณได้ ไม่นานหลังจากที่เราเริ่มใช้ Robolectric เราก็เริ่มใช้ Travis เป็น CI ของเราและพวกมันก็เล่นได้ไม่ดีนัก ฉันเดาว่าคุณสามารถส่งไปยังแอปพลิเคชันของคุณหรือคุณอาจต้องสร้างนักวิ่งที่กำหนดเองเพื่อให้สามารถเข้าถึงได้ด้วยวิธีนี้ ขอให้โชคดี
drspaceboo

ขอบคุณสำหรับตอนนี้ฉันเพิ่งติดRobolectric.application
Denis Kniazhev

6
Robolectric.getShadowApplication ()ไม่พร้อมใช้งาน
IgorGanapolsky

1

เห็นด้วยกับคำตอบของ @EugenMartynov และ @rds ....

สามารถดูตัวอย่างสั้น ๆ ได้ที่ Volley-Marshmallow-Release

ใน NetworkImageViewTest.java

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

ลิงค์วอลเลย์สามารถใช้ได้ https://android.googlesource.com/platform/frameworks/volley/+/marshmallow-release

คุณต้องเพิ่มการอ้างอิงในโมดูลวอลเลย์ใน android studio เป็น:

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


1

ในกรณีของคุณฉันคิดว่าคุณควรคำนึงถึงสิ่งที่คุณกำลังทดสอบอยู่จริงๆ บางครั้งการทำงานในเรื่องของการuntestableรหัสหรือโค้ด untestable ดูเหมือนจะเป็นสัญญาณว่าอาจจะรหัสของคุณจะต้อง refactored

สำหรับการตอบกลับการเรียก API คุณอาจไม่ต้องการทดสอบการเรียก API เอง อาจไม่จำเป็นต้องทดสอบว่าเป็นไปได้ที่จะส่ง / รับข้อมูลจากบริการเว็บใด ๆ โดยพลการ แต่รหัสของคุณจะจัดการและประมวลผลคำตอบของคุณในคฤหาสน์ที่คาดหวัง

ซึ่งในกรณีนี้อาจเป็นการดีกว่าที่จะ refactor โค้ดที่คุณพยายามทดสอบ แยกการแยกวิเคราะห์การตอบกลับ / การจัดการไปยังคลาสอื่นซึ่งยอมรับแบบง่ายStringและทำการทดสอบของคุณในคลาสนั้นโดยการฉีดการตอบกลับสตริงตัวอย่าง

สิ่งนี้จะมากหรือน้อยตามแนวคิดเรื่องSingle Responsibility and Dependency Inversion (The S and D in SOLID )


1

โอเคฉันรู้ว่าคนอื่น ๆ พูดคำตอบนี้มาก่อนและอาจล้าสมัยไปแล้ว

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

ฉันได้ค่าว่างเนื่องจากส่วนเมื่อ () อยู่หลังจากการเริ่มต้น sut อาจช่วยคุณได้บ้าง

ฉันยังมีไฟล์

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

ที่จุดเริ่มต้นของชั้นเรียน

นอกจากนี้

 when(mockApplication.getApplicationContext()).thenReturn(RuntimeEnvironment.application.getApplicationContext()); works
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.