Sometime getting main-thread checker warning on Unit-test #926
-
Hi everyone, So I have this code in my reducer case let .searchTextFieldChanged(keyword):
struct SearchID: Hashable {}
state....
guard !keyword.isEmpty else {
state....
return .cancel(id: SearchID())
}
return Effect.task {
do {
return Action.searchResponse(.success(try await environment.search(keyword)))
} catch {
return Action.searchResponse(.failure(error as! AppError))
}
}
.debounce(id: SearchID(), for: 0.3, scheduler: environment.mainQueue)
.receive(on: environment.mainQueue)
.eraseToEffect() And the environment looks like this struct SearchEnvironment {
var search: (String) async throws -> [Item]
var mainQueue: AnySchedulerOf<DispatchQueue>
} I tried to write a test for the reducer, and it look like this func testSearchShouldFail() {
let store = TestStore(
initialState: SearchState(),
reducer: searchReducer,
environment: SearchEnvironment(
search: { _ in throw AppError.unauthorized },
mainQueue: .immediate
)
)
store.send(.searchTextFieldChanged("iOS")) {
$0....
}
store.receive(.searchResponse(.failure(.unauthorized))) {
$0....
}
store.send(.searchTextFieldChanged("")) {
$0....
}
} And the problem is when I try to run the test, sometime I'll get this warning and then it will fail on the
But when running on simulator, all the actions landed on main-thread just fine. So, anyone know which part did I done wrong in my implementation ? |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 1 reply
-
Hi @khairilushan, this is happening because the This doesn't happen when running the app because there you are using a regular In order to get this to work you will need to use a live Note that we do not really recommend using We are working on some tools in the short term that will make it possible to use |
Beta Was this translation helpful? Give feedback.
Hi @khairilushan,
this is happening because the
.immediate
scheduler simply performs its work right away, on whatever thread it happens to be on. So, in tests, when you run the reducer and cause the effect toawait
it switches to a new thread, and then delivers its output to the store on a background thread.This doesn't happen when running the app because there you are using a regular
DispatchQueue.main
.In order to get this to work you will need to use a live
DispatchQueue.main
in your tests, which means you will need to performawait Task.sleep
in the test in order to wait for schedulers to do their work. This also means you will need to make your testasync
, which then means you will …