Coder Social home page Coder Social logo

mockable-ts's Introduction

mockable-ts

A very simple and lightweight library to mock code across integration tests.

example

Suppose we have the following app:

// app.ts
import database from "./database";

export const run = () => {
  database.execute("DELETE * FROM users");
};

// database.ts
export default {
  execute: (sql: string) => {
    /* DB code */
  },
};

Now if we want to write an integration test that does not call the database, we can make the database code mockable like this:

// database.ts
import { mockable } from "mockable-ts";

export default mockable({
  execute: (sql: string) => {
    /* DB code */
  },
});

And in our unit test we can then override the database like this:

// app.spec.ts
import { override } from "mockable-ts";
import { run } from "./app";
import database from "./database";

describe("app", () => {
  it("deletes users", () => {
    override(database, {
      execute: (sql) => {
        console.log(`would execute SQL ${sql}`);
      },
    });
    run();
  });
});

how does it work?

If you call mockable in production (NODE_ENV != 'TEST'), it just returns the value passed in, so it has absolutely no runtime performance impact. It only has a very small startup performance impact. If you call mockable in tests (NODE_ENV == 'TEST') it returns a proxy that forwards all calls to the original value passed into it, so it behaves exactly the same and code using it won't notice a difference. But the target value for those calls can then be swapped out at runtime using override or reset using reset

why not use X instead?

dependency injection

With dependency injections your whole codebase has to be written in a certain way. If that's not the case, good luck! If you consider using dependeny injection just for being able to mock out stuff... well, you probably shouldn't. If you have a more advanced use case where you need to swap out components based on configuration, the dependency injection might be the right choice.

jest mocks

Jest mocks are really hacky and it's often not obvious how it behaves. Jest mocks out entire files by default, which is often not what you want. If you want to mock just a single function, it gets messy. In mockable-ts its much more explicit what is mockable and it's completely indepentent of the module system. So no hacks. Another problem with jest mocks is that you usually have to specify the path to the file twice which is not dry, and the second one usually gets forgotten.

here's what I mean:

import module from "./my-module";

jest.mock("./my-module"); //don't forget to add this!

goals

  • Provide functionality to make code mockable
  • Provide functionality to mock code in tests
  • Provide functionality to get original implementation and reset mocks
  • Typesafety
  • Infer types whenever possible
  • No runtime performance impact
  • As little startup performance impact as possible
  • Easy refactoring
  • Module-system agnostic

non-goals

  • Provide functionality to create mock objects (the stuff passed in to override)
  • Provide functionality to verify interactions with mocks

reference

mockable<T extends object|function>(value: T): Proxy

Wraps your object or function and returns a proxy that behaves exactly like the original. Wrap every object or function with this that you want to override in your tests. We recommend not wrapping anything until it's needed in a test.

override(proxy: Proxy, value: T): void

Override the value of a proxy with a new one. Only call this in tests.

reset(proxy: Proxy): void

Reset a proxy to the original value

resetAll(): void

Reset all proxies to the original value

original(proxy: Proxy): T

Get the original value of a proxy

license

MIT

mockable-ts's People

Contributors

vancoding avatar

Watchers

 avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.