Mock dependencies with Mocha and Typescript - node.js

I have a typescript project which uses mocha. Let's say we have two modules as follows.
// http.ts
export class Http {
}
// app.ts
import Http from './http';
export class App {
}
How could I mock the Http module when I'm testing the App?
The test is executed through the npm script as below.
"test": "cross-env NODE_ENV=test ./node_modules/mocha/bin/mocha",
And the mocha options (mocha.opts) looks like below.
test/setup.ts
--compilers ts:ts-node/register
--compilers tsx:ts-node/register
./src/**/*.spec.ts

ts-mock-imports gives you run time control over your imports and maintains type safety.
in app.spec.ts
import * as httpModule from 'http';
import { App } from '../src/app';
import { ImportMock } from 'ts-mock-imports';
const httpMock = ImportMock.mockClass(httpModule, 'Http');
const app = new App(); // App now uses a fake version of the Http class
Now you can control how the Http module behaves in your tests.
Mock the response to a get:
httpMock.mock('get', { data: true });
const response = app.makeGetRequest(); // returns { data: true }

The import statement in typescript is compiled to require. You can use proxyquire to mock any dependencies in your tests

Related

How to mock electron when running jest with #kayahr/jest-electron-runner

Setup
I want to unit test my electron app with jest. For this I have the following setup:
I use jest and use #kayahr/jest-electron-runner to run it with electron instead of node. Additionally, since it is a typescript project, I use ts-jest.
My jest.config.js looks like this:
module.exports = {
collectCoverage: true,
coverageDirectory: 'coverage',
coverageProvider: 'v8',
preset: 'ts-jest',
runner: '#kayahr/jest-electron-runner/main',
testEnvironment: 'node',
};
The test is expected to run in the main process. I have reduced my code to the following example function:
import { app } from 'electron';
export function bar() {
console.log('in bar', app); //this is undefined when mocked, but I have a real module if not mocked
const baz = app.getAppPath();
return baz;
}
The test file:
import electron1 from 'electron';
import { bar } from '../src/main/foo';
console.log('in test', electron1); //this is undefined in the test file after import
// jest.mock('electron1'); -> this does just nothing, still undefined
const electron = require('electron');
console.log('in test after require', electron); //I have something here yay
jest.mock('electron'); //-> but if I comment this in -> it is {} but no mock at all
it('should mock app', () => {
bar();
expect(electron.app).toBeCalled();
});
What do I want to do?
I want to mock electron.app with jest to look whether it was called or not.
What is the problem?
Mocking electron does not work. In contrast to other modules like fs-extra where jest.mock() behaves as expected.
I don't understand the behavior happening here:
Importing "electron" via import in the file containing the tests (not the file to be tested!) does not work (other modules work well), but require("electron") does.
I do have the electron module if not mocked in bar(), but after mocking not
while jest.mock("fs-extra") works, after jest.mock("electron") electron is only an empty object, not a mock
I would really like to understand what I did wrong or what the problem is. Switching back to #jest-runner/electron does not seem to be an option, since it is not maintained anymore. Also I don't know if this is even the root of the problem.
Has anyone seen this behavior before and can give me a hint where to start searching?

"Cannot use import statement outside a module" got message when I try to mocha

I was using jest now on vue/nuxt.
And I am trying to change TDD by mocha and chai.
Installed mocha though npm i mocha --save-dev
package.json
"scripts": {
"test": "mocha"
},
test/list.spec.json
import { expect } from 'chai';
describe('test', function () {
it('should be rendered', function () {
const comp = [1, 2, 3];
expect(Math.max(...comp)).to.above(1);
});
});
Error message when I typed npm test
import { expect } from 'chai';
^^^^^^
SyntaxError: Cannot use import statement outside a module
What is problem with that ?
You cannot use the import syntax in a Node app (import { expect } from 'chai';) if your project isn't properly configured to use this newer syntax. The original Node syntax pre JS modules is const variable = require('./folder/file')
You have to set up Jest or the project you work on to work with ES6 Modules. In package.json, add "type": "module". Here's an explanation: https://www.geeksforgeeks.org/how-to-use-an-es6-import-in-node-js/

How to launch a chai test in node?

I have a node/typescript application. I'm trying to test routes with chai and chai-http. I can launch a file when I write an explicit name: yarn test myroute.test.ts, but yarn test at the root does nothing.
Also, the test is never performed. I only receive a Done in 0.06s. in my terminal. No "passed" or "failed".
Here is the test:
import chai from "chai";
import chaiHttp from "chai-http";
import { server } from "../index";
chai.use(chaiHttp);
const chaiApi = chai.request(server);
describe("GET /user/:id", () => {
it("return user information", async () => {
const res = await chaiApi
.get("/user/123")
.set("Cookie", "_id=567;locale=en");
chai.assert.equal(res.status, 200);
});
});
the package.json script is: "test": "test". I assume it's completely wrong, but chai doc says nothing about what to write here.
chai is an assertion library, similar to Node's built-in assert. It does NOT contain a test runner. You need to use mocha to collect and run your declared test suites and test cases.
After adding the mocha test framework, you can declare npm test script like this:
"test": "mocha --require ts-node/register --timeout 5000",
In order to run the TS test file, we need to specify ts-node/register. Use it like this:
yarn test myroute.test.ts

How to mock a import?

I am working on a tdd project with Node.js and Typescript. I have a class named HttpSample which is imported to another class named Sample as follows.
import {HttpSample} from "./httpService"
...
const http: HttpSample = new HttpSample();
http.get();
How can I mock the HttpSample class inside the Sample's test file?
Update
I am using Jasmine and mocha frameworks
ts-mock-imports is a library that is designed to fix this issue in Typescript while remaining type safe. It's built on top of sinon instead of Jasmine but will play nice with both.
In sample.spec.ts
import * as httpSample from './httpService';
import { ImportMock } from 'ts-mock-imports';
import { Sample } from './sample';
const httpMock = ImportMock.mockClass(httpSample, 'HttpSample');
// Sample will now get a mock version of HttpSample
const sample = new Sample();

Debbuging with Mocha and Chai ReactJS

I am trying to start writing some tests in an small app that I wrote from a React Tutorial
My Stack
node -> v8.7.0
mocha -> "^5.1.0"
jsdom -> "^11.8.0"
jquery -> "^3.3.1"
react-dom -> "^16.3.2"
react -> "^16.3.2"
chai -> "^4.1.2"
babel-register -> "^6.26.0"
Here is my test_helper
import { JSDOM } from 'jsdom';
import jquery from 'jquery';
import ReactTestUtils from 'react-dom/test-utils';
import React from 'react';
import ReactDOM from 'react-dom';
import { expect } from 'chai';
//Set up testing environment to run like a browser in the command line
const dom = new JSDOM('<!doctype html><html><body></body></html>');
global.window = dom.window;
global.document = dom.window.document;
const $ = jquery(global.window);
// Build a 'renderComponent' helper that should render a given react class
function renderComponent(ComponentClass) {
const componentInstance = ReactTestUtils.renderIntoDocument(<ComponentClass />);
return $(ReactDOM.findDOMNode(componentInstance));
}
//Build a helper for simulating events
//Set up chai-jquery
export { renderComponent, expect };
My board_test
import { renderComponent, expect } from '../test_helper';
import Board from '../../src/components/board';
describe('Board', () => {
it('exist', () => {
const component = renderComponent(Board);
expect(component).to.exist;
});
});
and in package.json I have
...
"scripts": {
...
"test": "mocha --require babel-register --require ./test/test_helper.js --recursive ./test",
"test:watch": "npm run test -- --watch"
}
...
When I run npm test I get this error, I understand that is related with renderComponent(...)
1) Board
exist:
TypeError: Cannot read property '0' of undefined
If someone want to download the project here is the link (the problem I am facing is under the branch addTests)
My Repo -> branch addTests
to change to the branch addTests
git checkout -b addTests origin/addTests
In your trunk
Delete your app_test in your test/component folder => (https://github.com/agusgambina/react-tic-tac-toe/tree/master/test/components).
Only if you are not using it, it seems to be a default boilerplate file
In your branch
You are testing board componenet without passing params.
in your code ( not testing ) this params are passing by game component.
I suggest you to modify your helper => (test\test_helper.js) to this
function renderComponent(ComponentClass,props) {
if (!props) props = {};
const componentInstance = ReactTestUtils.renderIntoDocument(<ComponentClass {...props}/>);
return $(ReactDOM.findDOMNode(componentInstance));
}
and your board test => (test\components\board_test.js) to:
const component = renderComponent(Board, YOUR_PROPS_HERE);
expect(component).to.exist;
now you can pass props to your renderComponent

Resources