Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

QUESTION: dependency injection for unit tests #1

Open
kpeters-cbsi opened this issue Oct 25, 2022 · 3 comments
Open

QUESTION: dependency injection for unit tests #1

kpeters-cbsi opened this issue Oct 25, 2022 · 3 comments

Comments

@kpeters-cbsi
Copy link

So how do you do dependency injection for testing with this framework? Say I have a function, listThings, implemented like so:


import type { Props } from '@exobase/core';
import makeStorageService, {
  StorageService,
} from '../storage-service';
import { useService } from '@exobase/hooks';
import _ from 'radash';
import config from '../config';

interface Args {
  listThingsArgs: any;
}

interface Services {
  storage: StorageService;
}

type Response = Array<string>;

async function listThings({args, services}: Props<Args, Services>): Promise<Response> {
  return this.services.storage.listThings(args.listThingsArgs)
}

export default _.compose(
  useService<Services>({
    storage: await makeStorageService(config.storageService)
  }),
  listThings
);

(As I'm sure you can deduce, I lifted a lot of this pattern from your published endpoint code)

So two things to note here:

First, there's no framework code here. While this is intended to run in Lambda / API Gateway, my goal is to be able to compose the framework code from Exobase with my function code so that I can very easily port this to another framework if need be.

Second, I'm loading my config in the function definiiton for listThings. If I want to use a custom config for my tests, how am I supposed to inject that? Or should I just mock the call to makeStorageService?

@kpeters-cbsi
Copy link
Author

Ah! I'm Doing It Wrong! What I need to do here is to abstract the function code into its own file and then compose it with useService in my framework code (e.g. Lambda).

So something like this:

import {
  StorageService,
} from '../storage-service';
import config from '../config';

interface Args {
  listThingsArgs: any;
}

interface Services {
  storage: StorageService;
}

type Response = Array<string>;

async function listThings({args, services}: {args: Args, services: Services}): Promise<Response> {
  return this.services.storage.listThings(args.listThingsArgs)
}

export default listThings;

And then in my endpoint Lambda:

import type { Props } from '@exobase/core';
import makeStorageService from '../storage-service';
import { useService, useCors } from '@exobase/hooks';
import { useLambda } from '@exobase/lambda'
import * as _ from 'radash';
import config from '../config';

export default _.compose(
  useLambda(),
  useCors(),
  useService<Services>({
    storage: StorageService
  }),
  ({args, services}: Props<Args, Services>) => listThings({args, services}) // I haven't tried this out, so I may be slightly off base here
)

@kpeters-cbsi
Copy link
Author

Leaving this open in case @rayepps or anyone else wants to comment further

@sodiray
Copy link
Owner

sodiray commented Oct 29, 2022

Hey @kpeters-cbsi thanks for bringing this up! So the way I do it is I keep it all in one file, I just export the endpoint function. In your first example, I would just add export to listThings so I can import it in my unit test.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants