I am having trouble mocking a simple dependency generator function.
//generatorFunction.js
export default ()=>({execute: (arg1)=>Promise.resolve(arg1)})
//actualFunction.js
import generate from 'generatorFunction'
export default (arg1)=>generate(arg1)
//actualFunction.test.js
import actualFunction from './actualFunction'
import generatorFunction from './generatorFunction'
const resultingGeneratedFunction = generatorFunction();
jest.mock('generatorFunction', ()=>jest.fn(()=>({execute: ()=>Promise.resolve()})))
it('calls generateFunction', function(done){
actualFunction(1).then(()=>{
expect(resultingGeneratedFunction.execute).toHaveBeenCalledOnce()
done()
})
})
which errors out as execute is never called, although when I console log inside of actualFunction is saw that execute was called.
The problem is that jest cant know you using a promise somewhere in your test. You have either return the promise from you use async/await. Have a look at the docs
import actualFunction from './actualFunction'
import generate from 'generatorFunction'
jest.mock('generatorFunction', ()=>jest.fn(()=>({execute: ()=>Promise.resolve()})))
it('calls generateFunction', function(){
return actualFunction(1).then(()=>{
expect(generateFunction.execute).toHaveBeenCalledOnce()
})
})
import actualFunction from './actualFunction'
import generate from 'generatorFunction'
jest.mock('generatorFunction', ()=>jest.fn(()=>({execute: ()=>Promise.resolve()})))
it('calls generateFunction', async function(){
const value = await actualFunction(1)
expect(generateFunction.execute).toHaveBeenCalledOnce()
})
Related
I have a very simple code structure like this
TestWorks.ts
const axios = require('axios');
export class TestWorks{
async getUsersList(param1:TestModel, userDetail:any){
console.log("BEGIN -- ... ");
And then this is my test class
MyTest.ts
const testworks = require("../src/interfaces/TestService/TestWorks");
it('Get Users', async () => {
var x = await testworks.getUsersList({}, {});
expect(x).to.be.an("object");
});
but I am seeing the following error, unable to figure out what the issue could be. The paths are definitely right, not an issue with the file paths of where the files are
Get Users:
TypeError: testworks.getUsersList is not a function
at C:\Users\xxxxxx\Documents\xxxxx\test\test-server.test.ts:53:28
testworks refers to the module (or whatever TypeScript exports) because you use require(). You should use import for TypeScript modules.
import { TestWorks } from '../src/interfaces/TestService/TestWorks';
i try to use the mocha utils stackTraceFilter() function
but i cannot find an example usage case where someone explains how to use it in ones test. I found the official tests here: link
But how can i implement it in my tests, which somehow look like that:
import { expect } from 'chai'
import 'mocha'
import { main, main2 } from './'
describe.only('index.ts', async () => {
it('should start a job', async () => {
// const R_RUN_MAIN = await main()
await main2()
// TEST
expect(1).to.equal(1) // fails
})
})
In the tests i can see the line
expect(filter(stack.join('\n')), 'to be', stack.slice(0, 3).join('\n'));
But how do i get the Stack for my test?
expect(1).to.equal(1) // fails
or in general, how do i get the stack and initialize the filter function for the whole file when, for example, code from an imported file is already failing and creating a long stack trace?
UPDATE (2018.08.15)
so i got mocha running in a programmatic way:
export {}
import * as MOCHA from 'mocha'
async function run() {
const mocha = new MOCHA({
reporter: 'progress',
reporterOptions: {
verbose: true,
},
})
mocha.addFile(`./src/utils/mocha/index.spec.ts`)
const R = mocha.run((failures) => {
process.on('exit', () => {
process.exit(failures)
})
})
}
run()
I dont know where to add and run the Filter function?
const filter = MOCHA.utils.stackTraceFilter
The stackTraceFilter() function in mocha isn't meant to filter your code, but rather the mocha internals that in theory shouldn't be relevant to your tests. You can view the source code, but to sum it up it just filters out 'mocha' and 'node' lines from the stack, depending on the environment you're in.
I think what you're looking for could be accomplished through the package StackTraceJS, which allows you to grab a stack from anywhere, and do what you want with it. We created a custom reporter for mocha which uses it, and it works quite well.
So, using the example from their site:
StackTrace.get()
.then(function(stack){
// you now have a stack, and can filter as you wish
})
.catch(function(err){});
I implemented basic caching functionality for a project and ran into a problem during the testing.
I test using jest and redis-mock and all the tests pass.
The problem is when I import a file which imports the redis-file.
The test-file doesn't exit.
Example:
index.test.js
import redis from 'redis'
import redis_mock from 'redis-mock'
jest.spyOn(redis, 'createClient').mockImplementation(red_mock.createClient)
import fileUsingRedis from './index'
describe('index', () => {
it('should pass', () => expect(true).toBeTruthy())
}
index.js
import {set} from './redis'
export default function ...
redis.js
import redis from 'redis'
const client = redis.createClient()
export function set(key, value) {...}
'1 passed'...'Ran all test suites matching ...'
But then it keeps waiting, I assume because the redis.createClient() is async or something or other. Seeing as it happens on the import I can't just resolve it.
Do I have to close the redis-instance connection after every test?
What is the solution/best-practice here?
So yeah, closing the instance did it.
index.test.js
import redis from './redis'
...
afterAll(() => redis.closeInstance())
redis.js
export function closeInstance(callback) {
client.quit(callback)
}
I've had trouble spying on exported function in a NodeJS (v9.6.1) app using Jasmine.
The app is written in typescript, transpiled with tsc in a dist folder to be executed as javascript.
App
I have a Foo utils file (foo.utils.ts) which exports functions:
import {readFile} from "fs";
export function getData(filePath: string){
const data = readFile(filePath)
// various checks happens here.
return data;
}
And a Bar class in a bar.ts file:
import {getData} from "../utils/foo.utils
export class Bar {
public do(){
// ... does stuff
const data = getData(filePath);
// etc.
}
}
Test
Now I'm trying to spyOn the exported getData method to check if it've been called and to return a mocked value. I don't want to read file in my unit test (and even to use the real getData method at all)
The bar.spec.ts file for testing:
describe("Bar", ()=>{
let bar: Bar;
beforeEach(function() {
bar = new Bar();
})
it(" should do stuff", ()=>{
const spy = spyOn(???, "getData").and.returnValue([]);
bar.do();
expect(spy).toHaveBeenCalled();
})
});
Problems
As it is a NodeJS app, I've been trying to use global as the object to spy on, but I get the error:
Error: : getAttachementData() method does not exist
I've also tried to add
import * as fooutils from ".../src/utils/foo.utils
And spy on fooutils but I still goes through the exported function (and crashes when it tries to read the file...)
Now I'm kinda lost. From what I've found it's not really possible to mock an exported function (even though they should be added to the global object).
I thought about refactoring the utils file to create an utils class which exports static method and spying on them.
Questions
Am I doing something wrong ?
Is it possible to spy (and replace) exported function ?
Would using static method in class (rather than export function) work ?
Any other way to that ?
You can wrap getData in an object { getData } and write your unit test as follows.
import { getData } from "../utils/foo.utils";
...
it(" should do stuff", () => {
const spy = spyOn({ getData }, "getData").and.returnValue([]);
bar.do();
expect(spy).toHaveBeenCalled();
});
Having done a lot of research I cannot find a way to mock functions that are exported with no parent object. For example I'm trying to mock functions exported the following way:
module.exports = function thing(event) {};
OR in ES6
export function thing(event) {};
When importing these into a test file I try importing like this:
import {thing} from 'emvio-util-responses;
//call some function that calls thing()
spyOn(???, 'thing').and.returnValue({});
expect(???.thing).toHaveBeenCalled();
I have tried many ways of accomplishing this but the mock is not called.
Some suggest importing * and providing an alias as a parent object. like this:
import * as SomeObj from 'emvio-util-responses;
//call some function that calls thing()
spyOn(SomeObj , 'thing').and.returnValue({});
expect(SomeObj .thing).toHaveBeenCalled();
This doesn't work.
Others suggest using the window object
spyOn(window, 'thing').and.returnValue({});
But I'm in node :(.
When you use es6 modules instead CommonJS all exports are named so you may use:
export default (event) => {}
and then import & spy as
import * as SomeObj from 'emvio-util-responses'
...
beforeEach(() => {
spyOn(someObj, 'default')
});