เขียนการทดสอบ JUnit เพื่อตรวจสอบข้อมูล SharedPreferences

ฉันยังใหม่กับการทดสอบหน่วยใน Android และความพยายามของฉันคือ assertTrue ว่าข้อมูลถูกส่งไปยังวิธีการสำเร็จและบันทึกใน SharedPreferences นี่คือการทดสอบของฉันจนถึงตอนนี้:

public class AuthTest {

    Authorization authorization = new Authorization();

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

    @Test
    public void test_IfAuthIsSaved() {
        //test if the auth object is saved in the auth object is saved as a.. 
        //..json string in Shared preferences
        Auth auth = mock(Auth.class);
        authorization.saveAuth(auth);

        //test if the auth is received and saved to sharedpreferences
    }

}

วิธี saveAuth:

public void saveAuth(Auth auth) {
    editor.putString("USER_AUTH", new Gson().toJson(auth));
    editor.commit();
}

การยืนยันนี้จะมีลักษณะอย่างไร?


person Dinuka Jay    schedule 29.09.2017    source แหล่งที่มา
comment
ลองดูสิ่งนี้: stackoverflow.com /คำถาม/35105545/   -  person Haresh Chhelana    schedule 29.09.2017


คำตอบ (3)


คุณกำลังล้อเลียน Auth ซึ่งไม่ได้โต้ตอบกับสิ่งใดในโค้ดของคุณ ดังนั้นคุณจึงไม่สามารถยืนยันใดๆ กับมันได้

คุณต้องเปลี่ยนวิธีการทดสอบ:

แนวทางที่ 1

  • จำลอง SharedPreferences.Editor และฉีดเข้าไปข้างใน Authorization
  • สร้างอินสแตนซ์ของวัตถุ Auth ใหม่และเรียกใช้ authorization.saveAuth(auth)
  • ยืนยันว่า editorMock.putString() ถูกเรียกใช้ด้วย json ที่คาดไว้
  • ยืนยันว่า editorMock.commit() ถูกเรียกใช้

วิธีนี้มีข้อเสียบางประการ:

  • การทดสอบของคุณควบคู่ไปกับการใช้งาน
  • หากคุณตัดสินใจที่จะจัดเก็บข้อมูล Auth ในรูปแบบอื่น คุณจะต้องเปลี่ยนการทดสอบ
  • คุณไม่ได้ทดสอบพฤติกรรมจริงๆ (ซึ่งคุณต้องการทำจริงๆ)

แนวทางที่ 2

  • สร้างการใช้งานปลอมของ SharedPreferences.Editor และแทรกเข้าไปภายใน Authorization
  • สร้างวัตถุ Auth ใหม่และเรียกใช้ authorization.saveAuth(auth)
  • เรียกข้อมูลการรับรองความถูกต้องหลังจากบันทึกโดยการเรียกใช้ authorization.getAuth() และยืนยันว่าเป็น Auth เดียวกับที่คุณบันทึกไว้

ข้อเสีย: * คุณต้องสร้างการใช้งาน ``SharedPrefereces.Editor`` ปลอมเพื่อวัตถุประสงค์ในการทดสอบที่จำลองพฤติกรรมเดียวกัน

ข้อดี: * การทดสอบของคุณไม่ได้ควบคู่ไปกับการใช้งาน * คุณสามารถเปลี่ยนการใช้งานได้โดยไม่ต้องเปลี่ยนการทดสอบ * คุณกำลังทดสอบพฤติกรรมไม่ใช่วิธีการ

การอ้างอิงบางส่วนเพื่อสำรองข้อมูลแนวทางที่สอง:

ตอนนี้ จากมุมมองทางเทคนิค การเรียกค้นออบเจ็กต์ที่เก็บไว้ถือเป็นส่วนย่อยของการสร้างสรรค์ เนื่องจาก ...

การออกแบบที่ขับเคลื่อนด้วยโดเมนโดย Eric Evans

person NewestStackOverflowUser    schedule 29.09.2017

คุณไม่จำเป็นต้องล้อเลียนคลาส Auth จริงๆ มันเกี่ยวกับ editor มากกว่า

1) ย้าย new Gson().toJson(auth) ไปยังวิธีการระดับแพ็คเกจแยกต่างหาก:

JSONObject toJson(Auth auth){
   return new Gson().toJson(auth);
}

2) การทดสอบ:

public class AuthTest {
    @InjectMocks
    @Spy
    Authorization authorization;

    @Mock
    private Editor editorMock;

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

    @Test
    public void test_IfAuthIsSaved() {
        // Arrange
       JSONObject jsonO = mock(JSONObject.class);

        Auth auth = mock(Auth.class);
        doReturn(jsonO).when(authorization).toJson(auth);            

        // Act
        authorization.saveAuth(auth);

        // Assert
        verify(editorMock).putString(Mockito.eq("USER_AUTH"), Mockito.eq(jsonO));
        verify(editorMock).commit();
    }

}

ฉันถือว่าตัวแก้ไขเป็นการพึ่งพาฟิลด์อินสแตนซ์

person Maciej Kowalski    schedule 29.09.2017

จะเกิดอะไรขึ้นถ้าตัวสร้างการอนุญาตมี SharedPrefrences

val sharedPreferences = Mockito.mock(SharedPreferences::class.java)
val editor = Mockito.mock(SharedPreferences.Editor::class.java)
Mockito.`when`(sharedPreferences.edit()).thenReturn(editor)

val authorization = Authorization(sharedPreferences)
val auth = ...
authorization.saveAuth(auth)

verify(editor).putString(...)
person illusionJJ    schedule 15.05.2019