← Назад к вопросам

Расскажи про опыт работы с MockContext

1.3 Junior🔥 142 комментариев
#Опыт и софт-скиллы#Тестирование

Комментарии (2)

🐱
deepseek-v3.2PrepBro AI6 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Мой опыт работы с MockContext в Android-тестировании

MockContext – это мощный инструмент из библиотеки тестирования Android, который позволяет создавать изолированные контексты для модульного тестирования компонентов, зависящих от Context. В моей практике я использовал его для тестирования классов, которые работают с ресурсами, системными сервисами или другими контекст-зависимыми операциями.

Ключевые сценарии использования MockContext

  1. Тестирование классов, использующих ресурсы (strings, dimens, drawables)
class ResourceManager(private val context: Context) {
    fun getWelcomeMessage(): String {
        return context.getString(R.string.welcome_message)
    }
}

// Тест с MockContext
@Test
fun testResourceManager() {
    val mockContext = MockContext()
    // Настройка ресурсов через ShadowResources (Robolectric)
    val resourceManager = ResourceManager(mockContext)
    
    // Для реального тестирования нужно настроить ресурсы
    // через Robolectric или другую библиотеку моков
}
  1. Изоляция тестов от реальной файловой системы
class FileStorage(private val context: Context) {
    fun saveData(data: String) {
        context.openFileOutput("data.txt", Context.MODE_PRIVATE).use {
            it.write(data.toByteArray())
        }
    }
}

// Тест с моком файловых операций
@Test
fun testFileStorage() {
    val mockContext = MockContext()
    val fileStorage = FileStorage(mockContext)
    
    // MockContext создает изолированное файловое пространство
    // что предотвращает влияние тестов на реальное приложение
}

Особенности и ограничения MockContext

Что MockContext предоставляет:

  • Базовую реализацию всех абстрактных методов Context
  • Изолированное файловое хранилище для операций с файлами
  • Пустые реализации методов для работы с ресурсами
  • Возможность создания тестовых компонентов (Service, Activity)

Что требует дополнительной настройки:

// MockContext не содержит реальных ресурсов
@Test
fun testWithResources() {
    val mockContext = MockContext()
    
    // Это вызовет исключение, если не использовать Robolectric
    // или другие инструменты для подмены ресурсов
    // mockContext.getString(R.string.app_name) // Будет ошибка
    
    // Решение: использовать Robolectric + тестовые ресурсы
}

Альтернативы и дополнения к MockContext

В своей практике я часто комбинирую MockContext с другими инструментами:

  1. Robolectric – предоставляет полноценный ShadowContext с реальными ресурсами
@RunWith(RobolectricTestRunner::class)
class ResourceTest {
    @Test
    fun testWithRobolectric() {
        val context = ApplicationProvider.getApplicationContext<Context>()
        // Теперь можно работать с реальными ресурсами в тестах
        val appName = context.getString(R.string.app_name)
        assertEquals("MyApp", appName)
    }
}
  1. AndroidX Test – предоставляет InstrumentationRegistry для инструментальных тестов
  2. Mockito – для создания кастомных моков Context с специфичным поведением
@Test
fun testWithMockito() {
    val mockContext = mock(Context::class.java)
    `when`(mockContext.packageName).thenReturn("com.test.app")
    
    val appInfo = AppInfo(mockContext)
    assertEquals("com.test.app", appInfo.getPackageName())
}

Практические советы по использованию

Когда использовать MockContext:

  • Для изолированного тестирования логики, минимально зависящей от реального Context
  • При необходимости быстрых юнит-тестов без зависимости от Android фреймворка
  • Для тестирования абстрактных классов, требующих Context

Когда выбрать другие подходы:

  • При тестировании работы с реальными ресурсами – использовать Robolectric
  • Для тестирования взаимодействия с системными сервисами – использовать Mockito
  • Для интеграционного тестирования – использовать Instrumentation тесты

Пример комплексного использования

class PreferencesManagerTest {
    private lateinit var mockContext: MockContext
    private lateinit var preferencesManager: PreferencesManager
    
    @Before
    fun setup() {
        mockContext = MockContext()
        preferencesManager = PreferencesManager(mockContext)
    }
    
    @Test
    fun testSaveAndLoadPreference() {
        // Act
        preferencesManager.saveSetting("key", "value")
        
        // Assert
        val loadedValue = preferencesManager.loadSetting("key", "default")
        assertEquals("value", loadedValue)
    }
    
    @Test
    fun testClearPreferences() {
        // Arrange
        preferencesManager.saveSetting("key1", "value1")
        preferencesManager.saveSetting("key2", "value2")
        
        // Act
        preferencesManager.clearAll()
        
        // Assert
        assertEquals("default", preferencesManager.loadSetting("key1", "default"))
        assertEquals("default", preferencesManager.loadSetting("key2", "default"))
    }
}

Вывод: MockContext – это ценный инструмент в арсенале Android-разработчика для написания изолированных модульных тестов. Однако его следует использовать осознанно, понимая ограничения и дополняя другими инструментами тестирования в зависимости от конкретных задач. В реальных проектах я обычно создаю фабрики для создания Context-зависимых объектов, что позволяет легко подменять реализации в тестах.

Расскажи про опыт работы с MockContext | PrepBro