How to implement AsyncTransformer in Jest? - jestjs

I am trying to use jest with the esbuild based project. I tried to use esbuild-jest-transform and esbuild-jest transformers, but in both cases, I got error Cannot use plugins in synchronous API calls from esbuild. This makes sense and I tried to implement AsyncTransformer instead.
But after switching from SyncTransformer to AsyncTransformer, I got the following error:
● Invalid synchronous transformer module:
".../node_modules/esbuild-jest-transform/index.js" specified in the "transform" object of Jest configuration
must export a `process` function.
which implies that it should be implemented in the old way. Here are more details about it.
Could you please tell, me how to make jest to use AsyncTransformer instead of SyncTransformer?
I tried to use import() as is described in the doc, but got the same result.

Related

What is differential between useFactory and useValues?

What is differential between useFactory and useValues who using for mock my module in createTestingModule on NestJS
I read Testing | NestJS and I read the article but found no explanation about the difference or when to use either mode.
Really, nothing more than useFactory accepts a function and could be used to inject values based on the current module while useValue is a direct value. There's really not much more to it than that. They're just custom providers

Error mocking a "non-strict" legacy module on Jest

I have some really messy non-strict-compliant legacy code on javascript, running just fine on NodeJs 12, and I'm trying to abstract it away and test the overlaying, new layers of code using Jest/Mocks.
But when I try to run the tests I receive the following error:
Test suite failed to run
SyntaxError: /legacy-path/messy_legacy_code.js: Legacy octal literals are not allowed in strict mode (557:66)
at Parser._raise (node_modules/#babel/parser/src/parser/error.js:60:45)
I'm trying to mock it away first thing on my test code, but still get this error. It seems that Jest is trying to parse it with Babel; it really won't find any compliant code there... It just runs on Node, nothing else.
I already tried mocking the legacy code itself and also tried making a container to "abstract" it away and mocking the container. But it seems Jest still tries to read every bit of noncompliant code behind it.
My modern.test.js code looks like this:
jest.mock('../../../../legacy-path/messy-container')
const { ModernLayer } = require('../../../../modern-path/modern-module');
Any ideas on how I cant completely block Jest from trying to read this noncompliant code and just mock it away?
jest.mock('...') performs auto-mock, unless a mock from __mocks__ is used. It tries to process module exports and fails on syntax error.
The module should be manually mocked instead:
jest.mock('../../../../legacy-path/messy-container', () => ({ ModernLayer: ... }));

Jest: Find out if current module is mocked during runtime

Is there a way i can find out during runtime if a module is mocked via jest?
Since mocked modules get required normally and therefore the code gets executed (as seen here: jest module executed even when mocked
We need this because we have checks on top of each file to fail early when a mandatory environment variable is not set, which causes our tests to fail even if the module is mocked.
if (!process.env.SOME_ENV) {
throw new Error(`Mandatory environment variable 'SOME_ENV' not set`)
}
We are looking for something like this:
if (!process.env.SOME_ENV && utils.isNotMocked(this)) {
throw new Error(`Mandatory environment variable 'SOME_ENV' not set`)
}
where utils.isNotMocked(this) is the magic function which checks if the module is currently mocked.
As #jonrsharpe mentioned, it is typically not desirable that software can distinguish whether it is under test or not. This means, you will probably not find the feature you are hoping for in any mocking framework. Moreover, there may be more fundamental problems to provide such a feature, because you might have mixed test scenarios where for some test cases an object of the mocked class is used, and for other test cases an object of the original class is used.
Since you are using the early exit mechanism as a general pattern in your code, as you describe: What about creating a library function for this check - which then again can be doubled during testing such that in that case the function does not throw?

Does verifying the mock is need in minitest

I'm reading the mocking capability of minitest.
require "minitest/autorun"
mock = MiniTest::Mock.new
mock.expect(:use_any_string, true, [String])
mock.use_any_string("foo")
## mock.use_any_string(1)
## MockExpectationError: mocked method :use_any_string called with unexpected arguments [1]
## I do not understand the purpose for this
mock.verify
So I do not understand the purpose of using mock.verify since the trying to pass any another type(to use_any_string) other than String result in mock expectation error.
So why should one use assert mock.verify then?
You are right, you cannot set anything else to the configured mock, but if your mock is not called at all, then you can find out with mock.verify. So if your method under test should call the mocked method, you should verify that it was called at all.
You are correct, mock.expect(:use_any_string, true, [String]) will cause the test to fail if the expected call is not made on the mock.
However using mock.verify depends on how you compose your test. In your example you are explicitly calling the method you are testing with mock.use_any_string("foo") so there is no need to also call mock.verify.
You could get into a scenario where you are not making this call explicitly, or are expecting the mock to have had calls made at a certain time. These scenarios would take advantage of mock.verify calls.
(Another note, minitest has recently introduced assert_mock which can be used instead of mock.verify)

mocking es6 modules in unit test

Suppose we have a file(source.js) to test:
// source.js
import x from './x';
export default () => x();
And the unit test code is very simple:
// test.js
import test from 'ava';
import source from './source'
test("OK", t => {
source();
t.pass();
});
But this is the tricky thing. The file "./x" does not exist in the test environment. Since it is a unit test, we do not need "./x". We can mock the function "x()" anyhow(using sinon or something else). But the unit test tool, ava, keeps showing "Error: Cannot find module './x'";
Is there any way to run the unit test without the file "./x"?
To do this, you'd need to override the import process itself. There are libraries for doing something similar-- overriding the require function with proxyquire, for example-- but these force you to invoke their custom function to import the module under test. In other words, you'd need to abandon using ES6 module syntax to use them.
You should also note that ES modules are only supported experimentally (and relatively recently) in Node. If you're transpiling with Babel, you're not actually using ES modules. You're using the syntax, sure, but Babel transpiles them to CommonJS "equivalents", complete with require calls and module.exports assignments.
As such, if you're using Babel, you can probably proxyquire to import modules under test in your test files, even if you're using ES module syntax in those modules. This will break, though, if you ever switch away from Babel. :\
My personal recommendation would be to avoid directly exporting anything you might need to stub. So functions like x should be in a static module imported like import foo from './foo' and invoked like foo.x(). Then, you can easily stub it with sinon.stub(foo, 'x'). Of course, the './foo' file will have to exist for this still, but what it really comes down to is how hardcore you want to be about TDD practices versus how much complexity you're willing to introduce to your mocking/stubbing process. I prefer relaxing the former to avoid the latter, but in the end it's up to you.
If you are using Jest, it can be achieved easily by mocking the import using the inbuilt mock method of jest.
Please refer the link below to find more about ES6 import mocks
https://jestjs.io/docs/en/es6-class-mocks
If you are using jest with JavaScript this is very simple:
use jest.mock('MODULE_NAME')
If it is a node module or your own module, no problem jest will automatically mock that module.

Resources