iOS Tests
There are two ways to test KMM iOS code: testing with Kotlin only and integration testing from iOS. Here is an introduction to both methods.
To understand the basics of testing, please refer to the Test documentation first.
Testing with Kotlin only
If you want to test Kotlin code only, you can write tests in Kotlin as usual.
You can use Koject.runTest()
or Koject.startTest()
to start a DI container for testing.
@Provides
class Controller
class SampleTest() {
@Test
fun test() = Koject.runTest {
val controller = inject<Controller>() // can be injected
}
}
Please refer to the Test documentation for more details.
iOS Unit Tests
To test including code written in Swift, use XCTest.
First, add the koject-test
dependency to the iosMain
source set in the build.gradle.kts
file of the shared module.
Use the main source set, not the test source set, to call from Swift.
kotlin {
/* ... */
sourceSets {
val commonMain by getting {
dependencies {
implementation("com.moriatsushi.koject:koject-core:1.3.0")
}
}
val iosMain by getting {
+ dependencies {
+ implementation("com.moriatsushi.koject:koject-test:1.3.0")
+ }
}
}
}
Create a KojectHelper
object and add startTest()
and stop()
functions.
object KojectHelper {
fun start() {
Koject.start()
}
fun startTest() {
Koject.startTest()
}
fun stop() {
Koject.stop()
}
}
You can test with the DI container for testing by calling startTest
in setUpWithError
and stop
in tearDownWithError
.
import XCTest
@testable import ios
@testable import shared
final class SampleStateTests: XCTestCase {
override func setUpWithError() throws {
KojectHelper.shared.startTest()
}
override func tearDownWithError() throws {
KojectHelper.shared.stop()
}
func test() throws {
/* ... */
}
}
iOS UI Tests
When performing UI tests, the DI container for the application is used, so branching must be done on the application side.
First, create a test branch in your entry point with the @main
attribute as follows:
import SwiftUI
import shared
@main
struct MyApp: App {
init() {
#if DEBUG
let isTesting = CommandLine.arguments.contains("TESTING")
if isTesting {
KojectHelper.shared.startTest()
} else {
KojectHelper.shared.start()
}
#else
KojectHelper.shared.start()
#endif
}
var body: some Scene {
/* ... */
}
}
Specify launchArguments
when starting the test, and UI tests can be executed using the DI container for testing.
import XCTest
final class UITests: XCTestCase {
let app = XCUIApplication()
func testSome() {
app.launchArguments = ["TESTING"]
app.launch()
/* ... */
}
}