Jest mocking multiple files and static methods - node.js

I am trying to write a test case using Jest. How can I write the test case for below snippets? A is a separate file and Three is a different file. I need to write the test cases as separate files as like unit test cases.
I am stuck in writing the static methods calling and mocking the multiple inputs. See below what I have tried also.
const one = require('../one');
const two = require('../two');
const three = require('../three');
class A {
public static checkTesting(param) {
switch (param) {
case 'one':
return one;
case 'two':
return two;
default:
return three;
}
}
constructor(param) {
this.testing = A.checkTesting(param);
}
}
module.exports = A;
const multiple = require('../multiple')(module);
const config = require('../config');
class Three {
public static sampleTestingWrite() {
return {
b: param => multiple[config.access](param)
};
}
constructor() {
this.sampleTesting = Three.sampleTestingWrite();
}
}
module.exports = Three;
A.test.js:
const One = require('../one');
const Two = require('../two');
const Three = require('../three');
const A = require('..');
jest.mock('../one');
jest.mock('../two');
jest.mock('../three');
describe('A test cases', () => {
test('should initiate the constructor', () => {
const mockStaticFunction = jest.fn();
mockStaticFunction.mockReturnValue('returns an object which does something on Multiple');
const MockA = new A('one');
console.log(MockA);
Console.mockImplementation(() => ({}));
console.log(logMedium);
expect(Console).toHaveBeenCalledTimes(1);
});
});

If you want to test if the constructor of A is called correctly. There is no need to mock one, two, three modules. Only you need to mock/spyOn is
checkTesting static method of A.
Here is the solution, I use typescript
import one from './one';
import two from './two';
import three from './three';
class A {
public static checkTesting(param) {
switch (param) {
case 'one':
return one;
case 'two':
return two;
default:
return three;
}
}
private testing;
constructor(param) {
this.testing = A.checkTesting(param);
}
}
export { A };
Unit test:
import { A } from './a';
describe('A', () => {
describe('checkTesting', () => {
it('should initiate the constructor', () => {
jest.spyOn(A, 'checkTesting').mockReturnValue({ name: 'never mind' });
const param = 'one';
const a = new A(param);
expect(a).toBeInstanceOf(A);
expect(A.checkTesting).toBeCalledWith(param);
});
});
});
Unit test result with coverage:
PASS src/mock-function/57624975/a.spec.ts
A
checkTesting
✓ t1 (8ms)
----------|----------|----------|----------|----------|-------------------|
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s |
----------|----------|----------|----------|----------|-------------------|
All files | 73.33 | 0 | 66.67 | 73.33 | |
a.ts | 66.67 | 0 | 66.67 | 66.67 | 7,9,11,13 |
one.ts | 100 | 100 | 100 | 100 | |
three.ts | 100 | 100 | 100 | 100 | |
two.ts | 100 | 100 | 100 | 100 | |
----------|----------|----------|----------|----------|-------------------|
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 1.649s, estimated 3s

Related

Sinon Class Constructor

I have an Animal class as follows
Animal.js
export default class Animal {
constructor(type) {
this.type = type
}
getAnimalSound(animal) {
if (animal && animal.type == 'dog') return 'woof'
if (animal && animal.type == 'cat') return 'meow'
}
}
I make a zoo module which has a method for getAnimalSound() as follows
zoo.js
import Animal from './Animal'
export default function getAnimalSound(type) {
let animal = new Animal(type)
let animalSound = animal.getAnimalSound(animal)
return animalSound
}
Now how do i make unit testing for zoo module?
zoo.test.js
import sinon from 'sinon'
import Animal from './Animal'
import getAnimalSound from './zoo'
let animalStub = sinon.createStubInstance(Animal)
let a = animalStub.getAnimalSound.returns('woof')
let sound = getAnimalSound('cat')
console.log(sound)
So the problem is that the 'new' has no effect by the way i have stubbed in test.js
Can i achieve this?
Regards
Bobu P
You could use Link Seams to mock your ./animal.js module and Animal class.
E.g.
animal.ts:
export default class Animal {
type: any;
constructor(type) {
this.type = type;
}
getAnimalSound(animal) {
if (animal && animal.type == 'dog') return 'woof';
if (animal && animal.type == 'cat') return 'meow';
}
}
zoo.ts:
import Animal from './animal';
export default function getAnimalSound(type) {
let animal = new Animal(type);
let animalSound = animal.getAnimalSound(animal);
return animalSound;
}
zoo.test.ts:
import sinon from 'sinon';
import proxyquire from 'proxyquire';
import { expect } from 'chai';
describe('61716637', () => {
it('should pass', () => {
const animalInstanceStub = {
getAnimalSound: sinon.stub().returns('stubbed value'),
};
const AnimalStub = sinon.stub().returns(animalInstanceStub);
const getAnimalSound = proxyquire('./zoo', {
'./animal': { default: AnimalStub },
}).default;
const actual = getAnimalSound('bird');
expect(actual).to.be.equal('stubbed value');
sinon.assert.calledWith(AnimalStub, 'bird');
sinon.assert.calledWith(animalInstanceStub.getAnimalSound, animalInstanceStub);
});
});
unit test results with coverage report:
61716637
✓ should pass (2242ms)
1 passing (2s)
-----------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
-----------|---------|----------|---------|---------|-------------------
All files | 54.55 | 0 | 33.33 | 66.67 |
animal.ts | 16.67 | 0 | 0 | 25 | 4-8
zoo.ts | 100 | 100 | 100 | 100 |
-----------|---------|----------|---------|---------|-------------------

Find parent folder with file in node js

I want to be able to find target.json by passing a path to startingPoint.txt to a function in Node JS, given the following folder structure:
- root
- sub1
- sub2
startingPoint.txt
target.json
I've found a node package for it called find-up, but this is the kind of thing that probably takes no more than 6 lines of code.
export function findUp(start: Path, target: string): Path | undefined {
// this code here
}
const pathToTarget = findUp("root/sub1/sub2/startingPoint.txt", "target.json"/);
console.log(pathToTarget); // "root/target.json"
Old question I know, but I've just had to implement something similar and spent ages trying to find a good solution.
So, for future explorers, heres my solution using path and fs modules.
const PATH = require('path');
const FS = require('fs');
function findInPathAncestry(path, target) {
let current_directory_path = PATH.normalize(path).split(PATH.sep);
let result = false;
while(current_directory_path.length && !result) {
let current_path = current_directory_path.join(PATH.sep)+PATH.sep+target;
if(FS.existsSync(current_path)) {
result = current_path;
}
current_directory_path.pop();
}
return result;
}
usage example:
// example file structure:
// C:\
// | - path\
// | --- to\
// | ----- start\
// | ------- at\
// | ----- findme.txt
let start_location = "C:\path\to\start\at";
let target_file = "findme.txt";
console.log(findInPathAncestry(start_location, target_file));
// expected output:
// C:\path\to\findme.txt
// or false if file doesn't exist in path
the use of PATH.normalize and PATH.sep allows this to work in windows and unix environments
https://nodejs.org/api/path.html#path_path_sep
Here's what I have for now:
import { join, dirname } from 'path';
import { existsSync } from 'fs';
export let MAX_BACK_STEPS = 50;
export function findUp(start: string, target: string, boundary?: {
path: string,
inclusive: boolean,
}): string | null {
let currentDir = dirname(start);
let lastTry = false;
let backSteps = 0;
while (backSteps++) {
if (backSteps >= MAX_BACK_STEPS) {
console.error("Too many back steps");
return null;
}
if (boundary && boundary.path.includes(currentDir)) {
if (boundary.inclusive && lastTry === false) {
lastTry = true;
} else {
return null;
}
}
const targetTestPath = join(currentDir, target);
if (existsSync(targetTestPath)) {
return targetTestPath;
}
currentDir = join(currentDir, "../");
}
}

Jest: mocking dependencies that are passed in to constructor

I'm stuck trying to mock a class that is passed in through constructor and all the examples I've encountered so far have initialized dependencies inside constructors.
From my understanding jest replaces such dependencies with its overridden constructor but because I'm passing in the dependencies myself I'm in need of a passable instance when initialising UnderTest.
For what it's worth I'm ideally looking for a Mockito-ish behaviour, something along the lines of.
const mockedDependency = ???
const underTest = new UnderTest(mockedDependency)
...
Proceed to write tests for underTest
This is the code I'm trying to test. Please assume that MockedDependency has its own dependencies, passed in to constructor as well.
export default class UnderTest {
private mockedDependency : MockedDependency
constructor(mockedDependency: MockedDependency) {
this.mockedDependency = mockedDependency
}
public methodUnderTest(parameter: string) {
const mockedResult = this.mockedDependency.returnSomething(parameter)
return this.doSomethingElse(mockedResult)
}
public methodUnderTest2(parameter1: string, parameter2: string) {
const mockedResult = this.mockedDependency.returnSomething2(parameter1, parameter2)
return this.doSomethingElse(mockedResult)
}
private doSomethingElse(mockedResult: string) {
return mockedResult
}
}
How would you go about unit testing UnderTest class?
Bonus points for a way to set the result of mockedDependency methods either in each test or by input.
Edit:
A possible solution to those who stumble upon the same issue:
It's possible to cast variable as the desired object and override the methods like so:
const mockedDependency = {
returnSomething(parameter: string) {
return parameter
}
} as MockedDependency
const underTest = new UnderTest(mockedDependency)
It's far from perfect but will do for simpler cases.
Thanks in advance!
Here is the solution:
UnderTest.ts:
export interface MockedDependency {
returnSomething(...args: any[]): any;
returnSomething2(...args: any[]): any;
}
export default class UnderTest {
private mockedDependency: MockedDependency;
constructor(mockedDependency: MockedDependency) {
this.mockedDependency = mockedDependency;
}
public methodUnderTest(parameter: string) {
const mockedResult = this.mockedDependency.returnSomething(parameter);
return this.doSomethingElse(mockedResult);
}
public methodUnderTest2(parameter1: string, parameter2: string) {
const mockedResult = this.mockedDependency.returnSomething2(parameter1, parameter2);
return this.doSomethingElse(mockedResult);
}
private doSomethingElse(mockedResult: string) {
return mockedResult;
}
}
UnderTest.spec.ts:
import UnderTest, { MockedDependency } from './UnderTest';
const mockedDeps: jest.Mocked<MockedDependency> = {
returnSomething: jest.fn(),
returnSomething2: jest.fn()
};
const underTest = new UnderTest(mockedDeps);
describe('UnderTest', () => {
afterEach(() => {
jest.resetAllMocks();
});
describe('#methodUnderTest', () => {
it('should correctly', () => {
mockedDeps.returnSomething.mockReturnValueOnce('mocked result');
const actualValue = underTest.methodUnderTest('1');
expect(actualValue).toBe('mocked result');
expect(mockedDeps.returnSomething).toBeCalledWith('1');
});
});
describe('#methodUnderTest2', () => {
it('should correctly', () => {
mockedDeps.returnSomething2.mockReturnValueOnce('mocked result');
const actualValue = underTest.methodUnderTest2('2', '3');
expect(actualValue).toBe('mocked result');
expect(mockedDeps.returnSomething2).toBeCalledWith('2', '3');
});
});
});
Unit test result with 100% coverage report:
PASS src/stackoverflow/55966013/UnderTest.spec.ts
UnderTest
#methodUnderTest
✓ should correctly (5ms)
#methodUnderTest2
✓ should correctly (1ms)
--------------|----------|----------|----------|----------|-------------------|
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s |
--------------|----------|----------|----------|----------|-------------------|
All files | 100 | 100 | 100 | 100 | |
UnderTest.ts | 100 | 100 | 100 | 100 | |
--------------|----------|----------|----------|----------|-------------------|
Test Suites: 1 passed, 1 total
Tests: 2 passed, 2 total
Snapshots: 0 total
Time: 3.597s, estimated 8s
Here is the completed demo: https://github.com/mrdulin/jest-codelab/tree/master/src/stackoverflow/55966013

Can I replace values in a table with SpecFlow.Assist?

I currently have a step to verify a payment
Then I have these payments:
| Payment Type | Amount |
| Cash | 1.20 |
I would like to replace the 'Amount' with a variable, such as bill total which would be in the TestContext.
Then I have these payments:
| Payment Type | Amount |
| Cash | <billTotal> |
I've attempted to pre-process the table before creating my set, but I cannot assign to the TableRow value. Is there a standard way to achieve this? Is there a different approach I should be taking?
I ended up using something like this before creating my set:
public void AdjustTable(Table table)
{
foreach (var row in table.Rows)
{
foreach (var key in row.Keys)
{
if (row[key] == "<userFirstName>")
{
row[key] = this.testContext.CustomerProfile.Customer.Name.First;
}
else if (row[key] == "<userLastName>")
{
row[key] = this.testContext.CustomerProfile.Customer.Name.Last;
}
}
}
}
Still open to suggestions!!

Slick print list of tables

I want to print a list of tables from the database I connect to via JDBC but cannot figure out how to do this. I have tried using MTable.getTables and defaultTables, thanks
import slick.driver.H2Driver.api._
import scala.concurrent._
import com.typesafe.config.{ ConfigFactory, Config }
object SlickTest {
def main(args: Array[String]): Unit = {
"""
|mydb = {
| driver = com.microsoft.sqlserver.jdbc.SQLServerDriver
| slickDriver = com.typesafe.slick.driver.ms.SQLServerDriver
| url="jdbc:sqlserver://#############"
| properties = {
| databaseName = "######"
| user = "#######"
| password = "########"
| }
| numThreads = 10
|}
""".stripMargin
val db = Database.forConfig("mydb")
???
}
}
There are quite a few different ways of doing this, but following the layout of the code you had in your question, this works for Slick 3.1 (and using freeslick profiles, because I don't have the slick extensions SQLServer lib).
import com.typesafe.config.ConfigFactory
import slick.backend.DatabaseConfig
import slick.driver.JdbcProfile
import scala.concurrent.duration.Duration
import scala.concurrent.{Await, ExecutionContext}
object SlickTest {
def main(args: Array[String]): Unit = {
val config = """
|mydb = {
|
| driver = "freeslick.MSJDBCSQLServerProfile$"
| db {
| driver = com.microsoft.sqlserver.jdbc.SQLServerDriver
| url="jdbc:sqlserver://localhost:2008"
| properties = {
| databaseName = "freeslicktest"
| user = "sa"
| password = "FreeSlick"
| }
| }
|}
""".stripMargin
val dbConfig = DatabaseConfig.forConfig[JdbcProfile]("mydb", ConfigFactory.parseString(config))
import ExecutionContext.Implicits.global
Await.result(dbConfig.db.run(dbConfig.driver.defaultTables), Duration.Inf).foreach(println)
}
}
produces this result for a database with one table called USERS in it.
*** (c.z.hikari.HikariDataSource) HikariCP pool mydb.db is starting.
MTable(MQName(freeslicktest.dbo.USERS),TABLE,null,None,None,None)
Process finished with exit code 0

Resources