How to inject dependencies in redux-sagas ?
How do I use DI in redux-sagas ?
You can do that with the Redux saga API, you have access to getContext
and setContext
methods that allow you to manage the context inside your sagas. Let's see how it works !
Inject your context
When you call createSagaMiddleware
you can pass a context. Later we will see how to get your context in your sagas
Here is how to inject context in redux-saga:
import { createUserService } from "...";
import createSagaMiddleware from "redux-saga";
const userService = createUserService(...);
const sagaMiddleware = createSagaMiddleware({
context: {
userService
}
});
sagaMiddleware.run(rootSaga);
Get your context
You can import getContext
from redux-saga/effects and then call getContext
with the key of the context that you want. So you will get userService
in this case.
import { getContext } from "redux-saga/effects";
export function* loadUsersSagas(action) {
const userService = yield getContext("userService");
const users = yield userService.loadUsers();
...
}
Testing
How we can test a context with redux-saga
You can use redux-saga-test-plan. The goal of this library is to test our sagas.
What we want to do ?
- Add mocked context in our tests
- Ensure we try to get the right item in the context
With provide
we give [[getContext("userService"), { loadUsers }]]
that's the mocked context for userService
.
With getContext
we test if we get the right item in the context here: userService
import { getContext } from "redux-saga-test-plan/matchers";
describe("Load users", () => {
it("should load mocked users", () => {
const loadUsers = () => Promise.resolve([johnDoe]);
const action = createAction(...);
return expectSaga(loadUsersSagas, action)
.provide([[getContext("userService"), { loadUsers }]])
.getContext("userService")
.call(...)
.put(...)
.run();
});
});
I hope my answer help you 😊