Thanks to visit codestin.com
Credit goes to github.com

Skip to content

TestFlex is a dependency inversion layer for your unit test code. Write your code with TestFlex, then use any test runner you want.

Notifications You must be signed in to change notification settings

DuncanWilder/testflex

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

16 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

TestFlex

This is a work in progress, so for now it's more of a concept than a library.

TestFlex is a dependency inversion layer for your unit test code. Write your code with TestFlex, then use any test runner you want.

The idea

Running Jest but want to try Bun? Maybe the Node.js test runner? What happens when Jest falls out of favour and we need to move away from it? jQuery was the best way to build websites, then Angular, then React, then Vue, then Solid, then Vite, then whatever else. You get the idea - things change, so tying ourselves to a single implementation or tool is perhaps not the best idea.

I appreciate the irony in me recommending tying yourselves to TestFlex! But it's less about the tool and perhaps more about the design pattern. If we depend on an abstraction layer rather than a concrete implementation, we can keep ourselves more flexible to changes in the future.

Test runners and some notes on them

Test runner Weekly downloads it/test describe global expect (not via it) mocking (e.g. spies/function mocks) ESM module mocking
Jest 22,060,565
Bun ???
Vitest 3,457,771
Jasmine 1,434,086 ⚠️ It might be possible using testdouble?
Node test runner I'm sure a lot
Mocha 7,300,267
Modern Web Test Runner 48,087 Not supported
uvu 2,853,593 ⚠️ "Suite"s
AVA 267,968
Supertape 417 ⚠️ Yes, with mock-import
Tap 168,881 ⚠️ Yes, with @tapjs/mock

Karma is deprecated, so not being considered.

Learnings from these investigations

ESM module mocking is hard

When I say module mocking, I'm referring to something like this (contrived) example using Jest;

// Mock the whole file, not just the function
import math from './math';

jest.mock('./math', () => ({
  add: jest.fn().mockImplementation((a, b) => {
    return a + b;
  })
})

it('should add', () => {
  expect(math.add).toHaveBeenCalled();
  expect(math.add(1,2)).toEqual(3);
});

// Rather than mocking/spying on the individual function
import math from './math';

spyOn(math, 'add', (a, b) => {
  return a + b;
});

it('should add', () => {
  expect(math.add).toHaveBeenCalled();
  expect(math.add(1,2)).toEqual(3);
});

This mocking of the whole module means that other systems that import the same module also share the same mock.

It looks like you can mock require statements fairly easily with tools like cjs-mock or proxyquire, but import statements are harder. I think there is something in the ES specification that states that imports should be immutable, which makes mocking out the whole module "difficult".

testdouble seems to think it's possible, but it requires compiling down the CJS first.

I wonder if this is what Jest is doing under the hood before every test is run 🤔 (and why it's so slow comparatively)

Is Dependency Injection the answer to module mocking?

So it seems that mocking out a whole file is handy, but not often the way to do things. Is Dependency Injection (DI) the answer? I spent about 30 minutes talking to ChatGPT on the topic, and from what I can tell DI can help get around this issue. It does make code more testable. But the problem is that it comes with a lot of overheads. You have to establish and maintain "DI Containers" - but where are the boundaries to these containers? As a React developer, I know the pain of prop drilling. Do I now need to instantiate this container and "prop drill" it down from some top-level area to the place I need it to be consumed?

I'm torn on DI. It seems like it would make things easier, but it also feels very much a relic of Object Orientated languages that had no concept of functional programming, or how JS works. DI was a great way to overcome these limitations, but does that apply in a JS world?

I'm going to go away and ponder that fact. I might try and see how it looks/works on my jobs' codebase. No better acid test than seeing how it works in the "real world".

About

TestFlex is a dependency inversion layer for your unit test code. Write your code with TestFlex, then use any test runner you want.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 2

  •  
  •