Платформы Mobile Backend as a Service (MBaaS) ускоряют разработку, предоставляя готовую backend инфраструктуру. Однако тестирование MBaaS интеграций требует иных стратегий, чем традиционное API тестирование. Это руководство охватывает тестирование Firebase, AWS Amplify и Supabase в мобильных приложениях.

Понимание Вызовов MBaaS Тестирования

Уникальные Характеристики

ХарактеристикаТрадиционное APIMBaaS
АутентификацияКастомные endpointsУправляемая (OAuth, Social Login)
Синхронизация ДанныхRequest/ResponseListeners в реальном времени
Offline РежимРучная реализацияВстроенное кэширование
Хранилище ФайловКастомные upload endpointsУправляемые storage buckets
Push УведомленияСторонние сервисыИнтегрированная отправка
Подход к ТестированиюHTTP mockingSDK mocking + Эмуляторы

При тестировании MBaaS платформ тестирование производительности API становится критически важным для мониторинга квот, задержек и эффективности синхронизации в реальном времени.

Firebase Тестирование

Firebase Local Emulator Suite

Настройка:

# Установить Firebase CLI
npm install -g firebase-tools

# Инициализировать Firebase в проекте
firebase init

# Запустить эмуляторы
firebase emulators:start

Android Firebase Testing

Firestore Test:

import com.google.firebase.firestore.FirebaseFirestore

class UserRepositoryTest {
    private lateinit var firestore: FirebaseFirestore

    @Before
    fun setUp() {
        firestore = FirebaseFirestore.getInstance().apply {
            useEmulator("10.0.2.2", 8080)
            firestoreSettings = FirebaseFirestoreSettings.Builder()
                .setPersistenceEnabled(false)
                .build()
        }
    }

    @Test
    fun testCreateUser() = runTest {
        val user = User(
            id = "test-user-1",
            username = "тестовыйпользователь",
            email = "test@example.com"
        )

        userRepository.createUser(user)

        val snapshot = firestore.collection("users")
            .document("test-user-1")
            .get()
            .await()

        assertTrue(snapshot.exists())
        assertEquals("тестовыйпользователь", snapshot.getString("username"))
    }

    @Test
    fun testRealtimeUserUpdates() = runTest {
        val updates = mutableListOf<User>()

        val job = launch {
            userRepository.observeUser("test-user-1").collect { user ->
                user?.let { updates.add(it) }
            }
        }

        val user = User(id = "test-user-1", username = "оригинальный")
        userRepository.createUser(user)
        delay(100)

        userRepository.updateUsername("test-user-1", "обновлённый")
        delay(100)

        job.cancel()

        assertEquals(2, updates.size)
        assertEquals("оригинальный", updates[0].username)
        assertEquals("обновлённый", updates[1].username)
    }

    @Test
    fun testOfflineMode() = runTest {
        firestore.firestoreSettings = FirebaseFirestoreSettings.Builder()
            .setPersistenceEnabled(true)
            .build()

        val user = User(id = "offline-user", username = "offline-test")
        userRepository.createUser(user)

        // Симулировать offline режим
        firestore.disableNetwork().await()

        // Читать из кэша
        val cachedUser = userRepository.getUser("offline-user")
        assertNotNull(cachedUser)
        assertEquals("offline-test", cachedUser?.username)

        // Писать в offline
        userRepository.updateUsername("offline-user", "обновлено-offline")

        // Включить сеть обратно
        firestore.enableNetwork().await()
        delay(500)

        // Проверить, что offline запись синхронизировалась
        val syncedUser = userRepository.getUser("offline-user")
        assertEquals("обновлено-offline", syncedUser?.username)
    }
}

Понимание мобильного тестирования для iOS и Android является важным при реализации MBaaS решений в различных мобильных окружениях.

AWS Amplify Тестирование

Amplify Mock Backend

Настройка:

# Установить Amplify CLI
npm install -g @aws-amplify/cli

# Инициализировать Amplify
amplify init

# Добавить API
amplify add api

# Запустить mock сервер
amplify mock api

Android Amplify Testing

import com.amplifyframework.api.graphql.model.ModelMutation
import com.amplifyframework.datastore.generated.model.Todo

class TodoRepositoryTest {

    @Test
    fun testCreateTodo() = runTest {
        val todo = Todo.builder()
            .name("Test Todo")
            .description("Тестирование Amplify")
            .build()

        val result = todoRepository.createTodo(todo)

        assertNotNull(result)
        assertEquals("Test Todo", result.name)
    }

    @Test
    fun testQueryTodos() = runTest {
        val todo1 = Todo.builder().name("Todo 1").build()
        val todo2 = Todo.builder().name("Todo 2").build()

        todoRepository.createTodo(todo1)
        todoRepository.createTodo(todo2)

        val todos = todoRepository.getAllTodos()

        assertTrue(todos.size >= 2)
        assertTrue(todos.any { it.name == "Todo 1" })
    }
}

Supabase Тестирование

Supabase Local Development

Настройка:

# Установить Supabase CLI
npm install -g supabase

# Инициализировать Supabase
supabase init

# Запустить локальный Supabase
supabase start

Android Supabase Testing

import io.github.jan.supabase.postgrest.from

class UserRepositorySupabaseTest {

    private val supabase = createTestSupabaseClient()

    @Test
    fun testCreateUser() = runTest {
        val user = UserDto(
            username = "тестпользователь",
            email = "test@example.com"
        )

        val created = supabase.from("users")
            .insert(user)
            .decodeSingle<UserDto>()

        assertEquals("тестпользователь", created.username)
        assertNotNull(created.id)
    }

    @Test
    fun testRealtimeSubscription() = runTest {
        val updates = mutableListOf<UserDto>()

        val channel = supabase.realtime.createChannel("users")
        channel.postgresChangeFlow<PostgresAction.Insert>(
            schema = "public",
            table = "users"
        ).onEach { change ->
            updates.add(change.record)
        }.launchIn(this)

        channel.subscribe()
        delay(200)

        supabase.from("users").insert(
            UserDto(username = "realtime-user", email = "rt@example.com")
        )

        delay(500)
        channel.unsubscribe()

        assertTrue(updates.any { it.username == "realtime-user" })
    }
}

Лучшие Практики Тестирования

1. Изолировать Тестовые Данные

@Before
fun setUp() {
    val testCollectionPrefix = "test_${UUID.randomUUID()}_"
    firestore.collection("${testCollectionPrefix}users")
}

@After
fun tearDown() {
    deleteTestCollections()
}

2. Мокировать Внешние Зависимости

class UserRepository(
    private val firestore: FirebaseFirestore,
    private val analytics: Analytics = FirebaseAnalytics.getInstance()
)

// В тестах, инжектить mock analytics
val mockAnalytics = mock<Analytics>()
val repository = UserRepository(firestore, mockAnalytics)

3. Тестировать Переходы Offline/Online

@Test
fun testOnlineOfflineTransition() = runTest {
    val user = userRepository.getUser("user-1")
    assertNotNull(user)

    firestore.disableNetwork().await()

    val cachedUser = userRepository.getUser("user-1")
    assertEquals(user, cachedUser)

    firestore.enableNetwork().await()

    val syncedUser = userRepository.getUser("user-1")
    assertEquals(user, syncedUser)
}

Безопасность имеет первостепенное значение при работе с аутентификацией и хранением данных на MBaaS платформах. Внедрение практик тестирования безопасности мобильных приложений обеспечивает защиту ваших backend сервисов от распространённых уязвимостей.

CI/CD Интеграция

GitHub Actions с Firebase Emulators

name: MBaaS Tests

on: [push, pull_request]

jobs:
  firebase-tests:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v3

      - name: Install Firebase CLI
        run: npm install -g firebase-tools

      - name: Start Firebase Emulators
        run: firebase emulators:start --only firestore,auth &

      - name: Run Android Tests
        run: ./gradlew connectedAndroidTest

Заключение

MBaaS тестирование требует:

  • Локальные Эмуляторы: Firebase, Amplify mock, Supabase local
  • Real-time Тестирование: Подписки, listeners, синхронизация данных
  • Offline Тестирование: Валидация кэша, верификация синхронизации
  • Мониторинг Производительности: Отслеживание квот, оптимизация

Стратегия Тестирования:

  1. Unit тесты с мокированными SDKs
  2. Интеграционные тесты с эмуляторами
  3. E2E тесты с staging MBaaS инстансами
  4. Мониторинг production метрик

MBaaS платформы ускоряют разработку, но требуют дисциплинированного тестирования для обеспечения надёжности, offline поддержки и оптимизации затрат.