The code base I work on is built by different teams who have access to different proprietary packages.
Normally this is fine, but if I want to make sure my code changes don't break for their builds, I need to build it as them and run the shared tests.
Here's a dummy example:
// in SharedComponent.tsx
import { ChildComponent } from 'variations/foo-bar';
const SharedComponent = () => <><ChildComponent /></>;
And the contents of variations/foo-bar/ChildComponent
vary based on how the code is built (in essence variations/foo-bar
is replaced by variations-team-awesome/foo-bar
when built by 'team-awesome' and variations-team-amazing/foo-bar
when build by 'team-amazing').
Here is an example:
// in variations-team-awesome/foo-bar/ChildComponent.tsx
import { DoThings } from '@proprietary-X/things'
const ChildComponent = () => <div>{DoThings()}</Div>
// in variations-team-amazing/foo-bar/ChildComponent.tsx
import { DoStuff } from '@proprietary-Y/stuff'
const ChildComponent = () => <div>{DoStuff()}</Div>
If I build the SharedComponent
for my jest tests as 'team-awesome' but their version of ChildComponent
imports something proprietary I don't have access to, then jest will fail saying it can't find the module.
However, if the imports in ChildComponent
are always mocked, then it won't get tested as part of SharedComponent
(assume it makes sense to not mock them in these examples).
How can I conditionally mock these imports (i.e. @proprietary-Y/stuff
and @proprietary-X/things
) for the different teams?
In this case, it's better to try and import, and only mock if it fails.
This works in either the test file itself:
// manual mock in a function
jest.mock(
'@proprietary-X/things',
() => {
try {
return jest.requireActual('@proprietary-X/things');
} catch {
console.log('module not found, mocking...');
}
return {
DoThings: () => 'mocked DoThings',
}
},
{ virtual: true },
);
n.b. virtual is needed when the mock is for a module that doesn't exist (which is won't depending on the team).
Or using __mocks__
folders (with a helper function):
const conditionallyMock = (module, mock = {}) => {
try {
return jest.requireActual(module);
} catch {
console.log(`module '${module}' not found, mocking...`);
}
return mock;
}
// in __mocks__/@proprietary-X/things
module.exports = conditionallyMock('@proprietary-X/things', {
DoThings: () => 'mocked DoThings',
});
// in __mocks__/@proprietary-Y/stuff
module.exports = conditionallyMock('@proprietary-Y/stuff', {
DoStuff: () => 'mocked DoStuff',
});
This should work smoothly for both teams, and only console log out module '${module}' not found, mocking...
when you locally build as the other team and run the shared tests.