The real benefits of this approach come when you want to write some tests. Because all the dependencies are injected, you can mock each dependency and test every scenario:


describe("GetMe", () => {
    const mockSessionManager = mock<ISessionManager>();
    const mockErrorManager = mock<IErrorManager>();
    const mockLogManager = mock<ILogManager>();
    const mockUserRepo = mock<IUserRepository>();

    const func = GetMe({
        [ContainerKeys.USER_REPOSITORY]: mockUserRepo,
        [ContainerKeys.LOG_MANAGER]: mockLogManager,
        [ContainerKeys.ERROR_MANAGER]: mockErrorManager,
        [ContainerKeys.SESSION_MANAGER]: mockSessionManager,
    });

    const session: UserSession = {
        accountId: "abc",
        userId: "123",
    };

    mockSessionManager.getSessionValues.mockReturnValue(session);

    const event: AuthenticatedEvent = {
        identity: {
            claims: session,
        },
    };

    const user: IUser = {
        id: "",
        name: "",
        emailAddress: "",
        status: UserStatus.ACTIVE,
        accountId: "",
        cognitoId: "",
    };

    beforeEach(() => {
        jest.clearAllMocks();
    });
    it("Should call session manager and use that userId ", async () => {
        await func(event);
        expect(mockSessionManager.getSessionValues).toHaveBeenCalled();
        expect(mockUserRepo.getById).toHaveBeenCalledWith(session.accountId, session.userId);
        expect(mockErrorManager.handleError).not.toHaveBeenCalled();
    });

    it("Should return the user found", async () => {
        mockUserRepo.getById.mockReturnValue(Promise.resolve(user));
        const result = await func(event);
        expect(result).toEqual(user);
    });

    it("should handle error", async () => {
        mockUserRepo.getById.mockRejectedValue("fails");
        await func(event);
        expect(mockErrorManager.handleError).toHaveBeenCalled();
    });
});