2013-04-10 3 views
7

В последние несколько дней я начал играть с roboguice, robolectric и mockito. У меня есть небольшое Android-приложение с экраном входа, содержащим AutoCompleteTextView для более быстрого ввода имени пользователя. Имена пользователей для AutoCompleteTextView хранятся в базе данных sqlite.
Mocking SQLite-Database при тестировании Активность с 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)); 
    } 
... 
} 

Я хочу проверить MainActivity с помощью robolectric, пытаясь издеваться базу данных с Mockito. Это мой тест-класс:

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

Вызов mainActivity.onCreate (нуль); запускает каскад ошибок, заканчивающийся в строке Курсор курсор = db.rawQuery (SQL_QUERY, null); мой getUserList-метода в моем 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; 
} 

Я прочитал, что Mock возвращается пустые заглушки Пустоты-методов, и возвращает нуль на любом другом методе. Поскольку я издеваюсь над классом SQLiteDBAdapter, я ожидаю, что вызов getUserList на моем издеваемом SQLiteDBAdapter возвращает null. Мне не совсем понятно, почему он обращается к оригинальному методу. Я предполагаю, что он по-прежнему использует оригинальный SQLiteDBAdapter, а не Mock. Что мне нужно сделать, чтобы исправить это и как оно работает? У меня кончились идеи, поэтому любая помощь приветствуется.

ответ

2

Отказывание базы данных для проверки DAO не имеет для меня никакого смысла. Что вы испытываете? База данных. Зачем это устранять?

Смещение базы данных имеет смысл после прохождения всех ваших испытаний DAO, и пришло время протестировать сервис, чтобы пользователи могли выполнять часть работы. Вы уже протестировали DAO и базу данных, и ваш тестовый сервис не должен быть интеграционным тестом. Во что бы то ни стало отмахивается в этом случае.

Я не знаю много о том, что вы издеваетесь, но когда я издеваюсь над интерфейсами моего создания. Макет предоставляет резервную реализацию для ссылки на интерфейс, которую использует мой клиент/тест.

Если вы пытаетесь издеваться над конкретным классом, я бы рекомендовал обернуть этот адаптер внутри реализации на основе интерфейса. Это будет лучшая абстракция, и вам будет легче высмеивать ваш интерфейс.

+0

Я хочу проверить свою активность входа. Эта активность использует базу данных для получения списка пользователей для AutoCompleteTextview. Я хочу заменить базу данных макетом, поэтому я могу проверить активность входа (кнопки и т. Д.), Не завися от базы данных. Я считал тестирование некоторых кнопок и EditText хорошим упражнением, так как я играю с robolectric и mockito всего на несколько дней. – Frank

+0

ОК, это другое - вы тестируете пользовательский интерфейс. Я предполагаю, что вы уже протестировали DAO, поэтому мои комментарии об услуге хранятся для вас. – duffymo

+0

Издевательский сторонний код делает для меня весь смысл в мире. Зачем вам тестировать чужой код? И почему вы хотите накладные расходы на ACTUALLY с базой данных. Когда вы тестируете DAO, вы не проверяете, что база данных или ее драйвер функционируют так, как вы ожидаете, вы проверяете, что ваше взаимодействие с базой данных так же, как вы ожидаете. Это как раз то, за что. например, дублирующиеся обновления не обнаруживаются при попадании в реальную БД, но обычно не ожидаются или не требуются. Это раскрывается макетом. К сожалению, вы не можете контролировать то, что насмехается, поэтому абстрагирование - единственный способ. –

Смежные вопросы