W ciągu ostatnich kilku dni zacząłem grać z roboguice, robolectric i mockito. Mam małą aplikację na Androida z ekranem logowania zawierającym AutoCompleteTextView do szybszego wpisywania nazwy użytkownika. Nazwy użytkownika dla AutoCompleteTextView są przechowywane w bazie danych SQLite.
Prześmiewanie bazy danych SQLite podczas testowania aktywności za pomocą Robolectric
public class MainActivity extends RoboActivity implements View.OnClickListener {
@InjectView(R.id.startScreen_Login_Button) private Button loginButton;
@InjectView(R.id.startScreen_Cancel_Button) private Button cancelButton;
@InjectView(R.id.startScreen_forgotPwd_TextView) private TextView forgotPWTextView;
@InjectView(R.id.startScreen_Username_AutoCompleteTextView) private AutoCompleteTextView loginUsernameAutoCompleteTextView;
@InjectView(R.id.startScreen_Password_EditText) private EditText loginPasswordEditText;
@Inject private SharedPreferences sharedPreferences;
@Inject SQLiteDBAdapter dbAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
loginButton.setOnClickListener(this);
cancelButton.setOnClickListener(this);
forgotPWTextView.setOnClickListener(this);
// Creating List for startScreen_Username_AutoCompleteTextView
List<User> userList = dbAdapter.getUserList();
ListIterator<User> it = userList.listIterator();
List<String> userStringList = new ArrayList<String>();
User user;
while (it.hasNext()) {
user = it.next();
userStringList.add(user.getName());
}
loginUsernameAutoCompleteTextView.setAdapter(new ArrayAdapter<String>(this, R.layout.select_page_row, userStringList));
}
...
}
Chcę przetestować główną działalność za pomocą robolectric, starając się szydzić bazy danych z Mockito. To jest mój test-klasa:
@RunWith(CustomRobolectricTestRunner.class)
public class MainActivityTest {
@Mock
SQLiteDBAdapter dbAdapter;
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
}
@Test
public void shouldHaveApplicationName() throws Exception {
String appName = new MainActivity().getResources().getString(R.string.app_name);
assertThat(appName, equalTo("OperationReport"));
}
@Test
public void testButtonsVisible()
{
MainActivity mainActivity = new MainActivity();
mainActivity.onCreate(null);
}
}
Wywołanie mainActivity.onCreate (null); rozpoczyna kaskadę błędów, kończąc na linii kursor kursora = db.rawQuery (SQL_QUERY, null); mojego getUserList-metody w moim SQLiteDBAdapter:
public List<User> getUserList() {
SQLiteDatabase db = getReadableDatabase();
List<User> userList = new ArrayList<User>();
String SQL_QUERY = "SELECT * FROM User;";
Cursor cursor = db.rawQuery(SQL_QUERY, null);
cursor.moveToFirst();
while (!cursor.isAfterLast()) {
User user = new User();
user.setUserUUID(cursor.getString(0));
user.setName(cursor.getString(1));
user.setPassword(cursor.getString(2));
user.setDateOfBirth(cursor.getString(3));
user.setStaffNumber(cursor.getString(4));
user.setActive(cursor.getInt(5));
user.setUserClass(cursor.getInt(6));
userList.add(user);
cursor.moveToNext();
}
cursor.close();
db.close();
return userList;
}
czytałem, że Mock powraca puste odcinki z pustych przestrzeni metod i zwraca NULL w przypadku każdej innej metody. Ponieważ kpię z klasy SQLiteDBAdapter, oczekuję, że wywołanie metody getUserList na moim wyśmianym SQLiteDBAdapter zwróci wartość null. Nie jest dla mnie jasne, dlaczego ma dostęp do oryginalnej metody. Sądzę, że nadal używa oryginalnego SQLiteDBAdapter, a nie makiety. Co muszę zrobić, aby to naprawić i jak to działa? Zabrakło mi pomysłów, więc każda pomoc jest doceniana.
Chcę przetestować moją aktywność logowania. Ta aktywność korzysta z bazy danych, aby uzyskać listę userList dla widoku AutoCompleteTextview. Chcę zastąpić bazę danych makietą, aby przetestować aktywność logowania (przyciski itp.) Bez uzależnienia od bazy danych. Rozważałem przetestowanie niektórych przycisków i EditTexta, ponieważ gram na robolektryku i mockito tylko przez kilka dni. – Frank
OK, to coś innego - testujesz interfejs użytkownika. Zakładam, że już przetestowałeś DAO, więc moje komentarze na temat usługi trzymają się za Ciebie. – duffymo
Kpiny z kodu strony trzeciej mają dla mnie sens. Dlaczego miałbyś testować czyjś kod? I dlaczego chcesz narzut na RZECZYWIŚCIE mając bazę danych. Podczas testowania DAO nie testujesz, czy baza danych lub jej sterownik działają zgodnie z oczekiwaniami, testujesz, że twoja interakcja z bazą danych przebiega tak, jak oczekujesz. Właśnie do tego służy fałszywy przykład. np. zduplikowane aktualizacje nie są odkrywane podczas uderzania w prawdziwą bazę danych, ale zazwyczaj nie są oczekiwane lub poszukiwane. Zostało to odkryte przez próbę. Niestety nie możesz kontrolować, co jest możliwe do wykonania, więc abstrahowanie jest jedyną drogą. –