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





Не думаю, что то, чего вы пытаетесь достичь, возможно (по крайней мере, легко). Что вам следует сделать, так это структурировать свой код таким образом, чтобы можно было внедрить зависимости, а затем вы можете использовать имитированные версии своих производственных классов в тестах.
Простой пример (в 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).