Написание теста 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``` для целей тестирования, которая имитирует то же поведение

Преимущества: * ваш тест не связан с реализацией * вы можете изменить реализацию без изменения теста * вы тестируете поведение, а не методы

Некоторые ссылки для резервного копирования второго подхода:

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

Дизайн, управляемый доменом, Эрик Эванс

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