I'm trying to imitate something very well-known in mock practice for Java applications, but this time using TypeScript and JEST.
Suppose I have a class Controller
who depends on a class Service
. The Controller
declares its dependency through the constructor, making the Service
to be mandatory.
I use a Dependency Injection (DI) library (tsyringe
) to resolve the dependencies in runtime, therefore the DI container will take care of creating an instance of the Service
and injecting it into the Controller
when the time comes.
For clarity, here it goes the source code for the Controller
:
import { scoped, Lifecycle } from "tsyringe";
import { RouteService } from "./RouteService";
import { RouteDTO } from "./view/RouteDTO";
@scoped(Lifecycle.ContainerScoped)
export class RouteController {
constructor(private routeService: RouteService) {}
public createRoute(route: RouteDTO): RouteDTO {
// business logic subject for testing
if (isBusinessLogicValid) {
return this.routeService.saveRoute(route);
} else {
throw Error("Invalid business logic");
}
}
}
and here goes the source code for the Service
:
import { scoped, Lifecycle } from "tsyringe";
import { UserSession } from "../user/UserSession";
import { RouteDTO } from "./view/RouteDTO";
@scoped(Lifecycle.ContainerScoped)
export class RouteService {
constructor(
private userSession: UserSession
) {}
public saveRoute(route: RouteDTO): RouteDTO {
// business logic and persistence
return route
}
}
I'm trying to mock the class RouteService
in a way so that I don't need to create an instance of it manually to unit test the RouteController
, otherwise, I'll need to resolve all downstream dependencies (meaning: RouteController
depends on RouteService
, RouteService
depends on UserSession
, UserSession
depends on ...).
In Java using Mockito I'd be able to do something like this:
RouteService routeServiceMock = mock(RouteService.class); // this'd be the goal
// mock definitions on routeServiceMock
RouteController controller = new RouteController(routeServiceMock);
RouteDTO newDTO = createRouteDTO();
RouteDTO savedDTO = controller.save(newDTO);
assertThat(savedDTO).isEqualsTo(newDTO);
//... other assertions
I've been looking at Jest documentation and I couldn't find anything equivalent. Does anybody know if such a thing is feasiable? If yes, how can I do that?
It seems I have found a workable solution for a while, but I'm not very happy with the structure of the solution. Basically, I have to double cast it
as unknown as RouteService
.I can do the following: