Xcode - установить другой класс для действий запуска и тестирования

Я работаю над приложением iOS (используя Objective-C и Xcode), и сейчас я пытаюсь установить другой класс для действия запуска и для действия тестирования и пока не могу этого добиться. Давайте представим, что есть цель А, а также цель для модульного теста, давайте назовем ее A_UnitTest (A_UnitTest тестирует цель А). Существует класс, отвечающий за процесс входа в систему. Назовем его LoginManager, который имеет метод входа в систему, и этот метод отвечает за вход в реальную систему. Также существует класс для поддельного входа с тем же именем и тем же интерфейсом, что и LoginManager, и он должен использоваться только для целей тестирования.

Во время выполнения действия к цели А подключен настоящий класс LoginManager, и все работает довольно хорошо, но во время тестового действия (когда выбрано A_UnitTest) и я запускаю модульные тесты - я хочу протестировать цель А Я хотел бы использовать поддельный LoginManager. Я могу вручную выбрать поддельный LoginManager для цели А (отменить выбор реального LoginManager и выбрать поддельный LoginManager для цели А), но я хотел бы, чтобы он работал автоматически. Я имею в виду, что я хотел бы просто выбрать цель A_UnitTest и тестовую цель А, но во время тестирования я хотел бы, чтобы вместо настоящего LoginManager использовался поддельный LoginManager. Вы знаете, могу ли я как-то это сделать в Xcode? Или я должен поставить какой-нибудь сценарий на предварительный этап?

Спасибо за помощь!

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
0
29
1

Ответы 1

Не думаю, что то, чего вы пытаетесь достичь, возможно (по крайней мере, легко). Что вам следует сделать, так это структурировать свой код таким образом, чтобы можно было внедрить зависимости, а затем вы можете использовать имитированные версии своих производственных классов в тестах.

Простой пример (в Swift, поскольку нет языкового тега):

Производство :

protocol LoginManagerProtocol {
    func loginWithCredentials(login: String, password: String)
}

class LoginManager: LoginManagerProtocol {

    func loginWithCredentials(login: String, password: String) {
        // perform your production login here
    }
}

class LoginViewModel {
    private let loginManager: LoginManagerProtocol

    init(loginManager: LoginManagerProtocol) {
        self.loginManager = loginManager
    }

    func loginUser(with login: String, password: String) {
        loginManager.loginWithCredentials(login: login, password: password)
    }
}

Тесты:

class LoginManagerMock: LoginManagerProtocol {

    var mock_loginWithCredentials: ((String, String) -> Void)?
    func loginWithCredentials(login: String, password: String) {
        mock_loginWithCredentials?(login, password)
    }
}

class LoginViewModelTests: XCTest {

    func test_loginUser_shouldPassCredentials_toLoginManager() {
        // Arrange
        let sampleLogin = "login"
        let samplePassword = "password"

        let loginManagerMock = LoginManagerMock()
        var capturedCredentials: (login: String, password: String)?

        loginManagerMock.mock_loginWithCredentials = { login, password in 
            capturedCredentials = (login, password)
        }

        // Act
        let sut = LoginViewModel(loginManager: loginManagerMock)
        sut.loginUser(with: sampleLogin, password: samplePassword)

        // Assert
        XCTAssertEqual(sampleLogin, capturedCredentials.login)
        XCTAssertEqual(samplePassword, capturedCredentials.password)
    }
}

Если вы используете Objective-C, можно использовать аналогичный подход или вы можете использовать одну из имитирующих библиотек (например, OCMock).

Другие вопросы по теме