【问题标题】:How to mock a dependent class without changing constructor parameters to optional in TypeScript & JEST?如何在不将构造函数参数更改为 TypeScript 和 JEST 中的可选参数的情况下模拟依赖类?
【发布时间】:2023-01-09 03:52:57
【问题描述】:

我正在尝试模仿 Java 应用程序模拟实践中非常著名的东西,但这次使用 TypeScript 和 JEST。 假设我有一个班级Controller,他依赖班级ServiceController 通过构造函数声明其依赖关系,使 Service 成为强制性的。 我使用依赖注入 (DI) 库 (tsyringe) 来解决运行时的依赖关系,因此 DI 容器将负责创建 Service 的实例,并在时机成熟时将其注入 Controller

为了清楚起见,这里是 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");
        }
    }
}

这是 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
    }

}

我正在尝试以某种方式模拟 RouteService 类,这样我就不需要手动创建它的实例来对 RouteController 进行单元测试,否则,我将需要解决所有下游依赖项(意思是: RouteController 取决于RouteServiceRouteService 取决于UserSessionUserSession 取决于...)。 在使用 Mockito 的 Java 中,我可以做这样的事情:

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

我一直在查看 Jest 文档,但找不到任何等效的东西。有人知道这样的事情是否可行吗?如果是,我该怎么做?

【问题讨论】:

    标签: typescript jestjs mocking tsyringe


    【解决方案1】:

    似乎我找到了一个可行的解决方案有一段时间了,但我对解决方案的结构不是很满意。基本上,我必须双重投射它as unknown as RouteService

    我可以执行以下操作:

    describe('Route controller test', () => {
    
        beforeEach(() => {
            let routeServiceMock: RouteService = {
                saveRoute: jest.fn(async route => route)
            } as unknown as RouteService
            routeController = new RouteController(routeServiceMock);
        })
    
       // ...
    }
    

    【讨论】:

      猜你喜欢
      • 2020-06-06
      • 1970-01-01
      • 1970-01-01
      • 2014-05-02
      • 2021-04-05
      • 2012-03-19
      • 2019-12-11
      • 2015-01-24
      • 1970-01-01
      相关资源
      最近更新 更多