I have a TypeScript source file that has the following import:
// myCode.ts
import * as x from 'dep';
...
export class myClass {
...
}
where dep is a Node package that's included as part of the npm install. myCode.ts is a simple class that just has three methods. I would like to mock the entire myClass from inside a Jest test script that is written to test another class, myMainClass.
The problem I'm having is that the dep code is running some initialization that I can't seem to bypass. The initialization code fails outside the "real" environment so I simply want to bypass this for test purposes. No matter what I try I get an error that looks something like this:
Test suite failed to run
Dynamic Linking Error: ... error text ...
5 | // myCode.js
> 6 | import * as x from 'dep';
| ^
Again, the error is expected since I don't have these libraries locally (and don't want them for unit testing).
I was hoping I could add a simple mock statement (e.g., jest.mock('myClass'), or something similar, that would bypass anything to do with myClass. That way the code causing the link error would not be executed.
I'm fairly new to using Jest. Hopefully, this is a simple ask and I'm just missing the obvious. Thanks for the help.
Related
Summary
I feel like I've hit my head against a wall too many times trying to figure out where I may be going wrong. I have a simple piece of typescript code:
import FormDataI from 'formdata-node'
const c = new FormDataI()
export { c }
That im trying to compile down to umd using rollup and typescript. For some reason, I cant seem to get it to compile correctly and instead receive an error message:
[!] Error: 'default' is not exported by node_modules/formdata-node/lib/FormData.js, imported by index.ts
https://rollupjs.org/guide/en/#error-name-is-not-exported-by-module
index.ts (1:7)
Any suggestions as to where I may be going wrong? Here is a sample project that throws the error.
Things I've tried
Playing with various typescript settings such as esModuleInterlop
Playing with the commonjs properties such as requireReturnsDefault
Stepping through the rollup code hoping to find the import error. It appears to not notice the export from formdata-node which is exported using module.exports.default and module.exports
UPDATE
In the case of the above situation, I could simply set it as a global/external since FormData is supported in the browser natively. The question is, why does this error appear at all though?
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: ... }));
I have a simple application that is imported from webpack. The imported project exports a class like this...
export class BaseApp{...}
import { BaseApp } from "./MyClass"
import OtherThing from "./Other"
....
export { BaseApp, OtherThing }
Next I try to extend it in another node/express project...
import { BaseApp } from "#mine/util";
export class FullApp extends BaseApp{... }
I get...
class FullApp extends _mine_util__WEBPACK_IMPORTED_MODULE_0__["BaseA
pp"]{
^
TypeError: Class extends value undefined is not a constructor or null
How do I extend a class I am importing from Webpack?
Update here is an example project that demonstrates the issue...
https://github.com/jrgleason/simple-webpack-node
Impossible to say for certain when there is clearly much more to the source. If anyone else sees this error, the first thing to look for is circular dependencies: a file depends on some other file that (likely indirectly) depends on the first. JS must start somewhere, will not be able to ensure that a file is defined at the time that another file needs it, and will not try to go back and fill in the blanks later.
If you have more than a couple import / require statements, I recommend periodically running a checker like Madge to find and optionally visualize any loops before they become hard to undo.
npm i --saveDev madge
node node_modules/madge/bin/cli.js --warning --circular --extensions js ./
I'm trying to write a Micronaut AWS Groovy Lambda which makes HTTPS calls out to another service. I have followed the MN Docs and have created my project using:
mn create-function hello-world -lang groovy
This gave me a skeleton "hello-world" project with a functional test that I can run.
I then tried to modify the Groovy function (hello.world.HelloWorldFunction) to inject an HTTP client with the intention of calling the API within my function:
import static io.micronaut.http.HttpRequest.GET
#Field #Inject #Client("https://www.googleapis.com/books/v1") RxHttpClient httpClient
Maybe<String> helloWorld() {
httpClient.retrieve(GET("/volumes?q=isbn:0747532699"))
.firstElement()
}
Having done this I now get an exception when I run the functional test:
08:51:25.269 [nioEventLoopGroup-1-5] ERROR
i.m.h.s.netty.RoutingInBoundHandler - Unexpected error occurred:
Failed to inject value for field [httpClient] of class:
hello.world.HelloWorldFunction
Path Taken: HelloWorldFunction.httpClient
io.micronaut.context.exceptions.DependencyInjectionException: Failed to inject value for field [httpClient] of class:
hello.world.HelloWorldFunction
Path Taken: HelloWorldFunction.httpClient
I'm almost certainly doing something wrong, but I'm at a bit of a loss in terms of how to figure out what. Hence grateful for any pointers.
Many thanks,
Edd
Found the answer to this. It's a bug in 1.0.0.M1. It's already fixed in master though so can be worked around by building Micronaut from source and using that.
In addition I discovered that I was returning a type that is unsupported by Lambda functions (Maybe<String>). After building MN from master and changing this to a supported return type everything is now working.
I'm developing a backend chat server. It's currently written in messy callback javascript so I'm considering porting it to scalajs.
I've been looking through the beginner's guides, but I can't find how to actually compile the project to a single javascript file that I can run with node (e.g. node ./target/scala_2.11/my-project.js).
How do you compile a single file that you can run directly as a node program, and not in the browser?
My code couldn't be simpler:
package example
import scala.scalajs.js
import js.Dynamic.{ global => g }
object ScalaJSExample extends js.JSApp {
def main(): Unit = {
g.console.log("*** Did something ***")
println("Trying to print something...")
}
}
sbt run correctly prints:
*** Did something ***
Trying to print something...
But when I run sbt fullOptJS and then node ./target/scala-2.11/example-opt.js nothing is printed to the console.
The example-opt.js does not contain the one line of JavaScript used to actually launch the code. It only defines example.ScalaJSExample().main() as a function, but it doesn't call it.
An easy way to make it call that function automatically is to instruct sbt to add the call at the end of the .js file with this sbt setting:
scalaJSOutputWrapper := ("", "example.ScalaJSExample().main();")
This will allow you to just invoke
node ./target/scala-2.11/example-opt.js