As the title mentioned. I would like to ask that how could i write the test code for this scenario?
Example... i have a class look like this.
let ABC = function()
{
this.title="sample"
};
Question is how do i use chai expect to check for the existences of ABC class?
Does expect chai do something like this?
Expect(ABC).to.be.a.class
I'm not sure if you had this answered yet but I had the same question and I just found out
so after requiring chai and the expect API
and after requiring the file where your class resides and setting up your test
you can ensure that:
it is a function with .to.be.a('function');
check that it is an instance of your class with
expect(className).to.be.an.instance.of(ClassName);
const chai = require('chai');
const expect = chai.expect;
const Card = require('../src/Card');
describe('Card', function () {
it.skip('should be a function', function () {
const card = new Card();
expect(Card).to.be.a('function');
});
it.skip('should be an instance of Card', function () {
const card = new Card();
expect(card).to.be.an.instanceof(Card);
})
})
Related
This question already has answers here:
how to reset module imported between tests
(2 answers)
Closed last year.
i have the following code in a file that i'm trying to test:
foo.js
let localEnv = (process.env.LOCAL_ENVIRONMENT).toLowerCase() === 'prod' ? 'prod' : 'stage';
currently, i set this value using setupFiles which points to env.js and it contains:
process.env.LOCAL_ENVIRONMENT = 'prod';
my question is, how do i change process.env.LOCAL_ENVIRONMENT to test (or anything else) in foo.test.js? Just need to do this in a single test, so this line will be covered in my test coverage.
I tried doing something like this but it didn't work...
foo.test.js
test('Nonprod', async () => {
process.env.LOCAL_ENVIRONMENT = 'test';
...
});
You can alter the value as you tried. However you have to take into account that in your original file you only access the variable when you first load this script. In order to make this work you have to do sth like this:
// in your test file foo.test.js
const prev = process.env.LOCAL_ENVIRONMENT
process.env.LOCAL_ENVIRONMENT = 'test'; // from now on the env var is test
const myModule = require('./foo.js'); // foo.js is executed and the var is read as test
process.env.LOCAL_ENVIRONMENT = prev; // change value back
This has some caveheats as you cant test multiple scenarios with this (as the module is only loaded in once).
If you want to test more scenarios you have multiple options:
One would be to split the logic and process.env.LOCAL_ENVIRONMENT apart, for example
function getLocalEnv(env = process.env.LOCAL_ENVIRONMENT) {
return env.toLowerCase() === 'prod' ? 'prod' : 'stage';
}
This function is now very easy to test and doesn't depend on env vars for that anymore
I found the answer on how to reset and re-require the tested module here:
how to reset module imported between tests
The most easier way to test it for a specific test case is to set the test into a describe scope and to apply / remove the env value in beforeAll / afterAll or beforeEach / afterEach hooks depending on your needs.
describe('Test example', () => {
describe('prod (default)', () => {
test('do the thing', () => {
doTheThing(); // process.env.LOCAL_ENVIRONMENT is by default 'prod' because of your setupFiles
});
});
describe('test env', () => {
const oldEnv = process.env.LOCAL_ENVIRONMENT; // or { ...process.env } to copy the whole env
beforeAll(() => {
process.env.LOCAL_ENVIRONMENT = 'test';
});
afterAll(() => {
process.env.LOCAL_ENVIRONMENT = oldEnv; // do not forget to do this
});
test('do the thing', () => {
doTheThing(); // process.env.LOCAL_ENVIRONMENT is 'test' here
});
});
});
I have a function that uses a stub over and over again in a loop. I would like to assert that certain arguments were passed in the first time it was used. How do you do that?
This documentation doesn't seem to give you a way: https://sinonjs.org/releases/latest/assertions/
But in the spy documentation, you can do this:
require("#fatso83/mini-mocha").install();
const sinon = require("sinon");
const referee = require("#sinonjs/referee");
const assert = referee.assert;
const jsdom = require("jsdom");
const JSDOM = jsdom.JSDOM;
const window = new JSDOM().window;
const document = new JSDOM("").window;
const jQuery = require("jquery")(window);
global.document = document;
describe("Return nth call", () => {
const sandbox = sinon.createSandbox();
beforeEach(() => {
sandbox.spy(jQuery, "ajax");
});
afterEach(() => {
sandbox.restore();
});
it("should inspect jQuery.getJSON's usage of jQuery.ajax", () => {
const url = "https://jsonplaceholder.typicode.com/todos/1";
jQuery.ajax(url);
const spyCall = jQuery.ajax.getCall(0);
assert.equals(url, spyCall.args[0]);
});
});
The thing is, I'm using a stub not a spy, so I don't think I can use that. The reason I'm using a stub is because I definitely want to force the return value of this test double to be a certain value. The sinon documentation is kind of fragmented, and I wasn't able to figure out a way to have a test double force a return value and also assert on the arguments that are passed into it for a specific call. How do you do both?
I see now that the stub object has a getCall method on it (thanks typescript). I guess a stub extends a spy.
I'm struggling with using spyOn as part of testing my utils.js module. I've tried various methods and approaches but all seem to yield the "expected mock function to have been called". For the record, other unit tests work OK, so there shouldn't be any issue with my actual test setup.
Below is a simplified test case with two functions and one test, and I can't even get these to work. Did I misunderstand the spyOn altogether?
// utils.js
function capitalHelper(string){
return string.toUpperCase();
}
function getCapitalName(inputString){
return capitalHelper(inputString.charAt(0)) + inputString.slice(1);
}
exports.capitalHelper = capitalHelper
exports.getCapitalName = getCapitalName
// utils.test.js
const Utils = require('./utils');
test('helper function was called', () => {
const capitalHelperSpy = jest.spyOn(Utils, 'capitalHelper');
const newString = Utils.getCapitalName('john');
expect(Utils.capitalHelper).toHaveBeenCalled();
})
I do ont use spyOn(), but jest.fn() instead for all mock scenario
In your case I would do the following
test('helper function was called', () => {
Utils.capitalHelper = jest.fn((s) => Utils.capitalHelper(s))
const newString = Utils.getCapitalName('john')
expect(Utils.capitalHelper.mock.calls.length).toBe(1)
})
First line could have simply be :
Utils.capitalHelper = jest.fn()
since you don't seem to be testing the returned value in your test :)
You can find more details on jest.fn() on the jest official documentation : https://facebook.github.io/jest/docs/en/mock-functions.html
----------------------- EDIT
I got it : the problem occurs because within your utils.js file, getCapitalName uses the defined function, not the one pointed by the export.
To be able to mock the function in use you could change your utils.js file to
// utils.js
const Utils = {
capitalHelper: string => string.toUpperCase(),
getCapitalName: inputString => Utils.capitalHelper(inputString.charAt(0)) + inputString.slice(1)
}
export default Utils
then the tests I gave before will work
I've been thinking about how to test particular functions used by other functions within the same file.
For example, say I have two functions within one file:
// validators.js
export const required = ...;
export const containsUppercase = ...;
export const containsNumber = ...;
export const password = (val) => [required, containsUppercase, containsNumber].every(f => f(val));
So clearly, the password validator depends on the required, containsUppercase and containsNumber functions. But what if I wanted to stub those out, so my tests didn't actually have to care about those functions or how they validate.
This is a simple, silly example, but I've ran into the same problem with more complex scenarios.
For example, if I try to do this with sinon, I might try doing this:
import * as validators from './validators';
sinon.stub(validators, 'required').returns(false);
sinon.stub(validators, 'containsUppercase').returns(true);
sinon.stub(validators, 'containsNumber').returns(true);
// test
expect(validators.password('notImportant')).toBe(false);
I tried doing this, but I couldn't get it to work. I found that I could get it to work, if I did something like this, though I haven't tested it.
const required = ...;
const containsUppercase = ...;
const containsNumber = ...;
const password = (val) => [ex.required, ex.containsUppercase, ex.containsNumber].every(f => f(val));
export default ex = {
required,
containsUppercase,
containsNumber,
password,
}
This solution is also ugly, since I now I'd have to worry about exporting the function in the right place, and also reference it through the export object.
Is there a cleaner way to do this? Or rather, what would be the best way to test these kinds of functions?
The pattern in the second snippet is correct. password should refer to object methods in order for them to be mocked outside of validators.js scope.
The way to achieve this behaviour naturally in JS is using this:
export class Validators {
required = (...) => { ... }
...
password = (val) => [this.required, ...].every(...);
}
export default new Validators;
Or, with normal (non-arrow) functions:
export default {
required(...) {
...
}
...
password(val) {
[this.required, ...].every(...);
}
}
In the second case required, etc. methods should be additionally bound if they use this when being called like [this.required, ...].every(...).
"but having to call password(requiredFn, uppercaseFn, numberFn, val) every time doesn't seem very appealing to me."
You can use default values for parameters:
const defaultValidators = [required, containsUppercase, containsNumber];
const password = (value, validators = defaultValidators) => validators.every(f => f(value));
That allows you to call both password('pass') and password('pass', [v => false]) and thereby stub your validation functions.
Let me start by saying that I am new to React and even newer to TDD coding in JavaScript. I am currently working on a React / Redux application where we are testing all of our components. Our current test suite consists of Jasmine, Mocha, Chai, Karma, and skin-deep. For some of our components we are using skin-deep (see below -- skin deep is )
import sd from 'skin-deep';
describe('testing-text-editor', () => {
let tree;
let instance;
let vdom;
let field;
let fieldInput;
let callbackFunction;
beforeEach(() => {
field = 'description';
fieldInput = '<div>I am the description</div>';
callbackFunction = () => console.log('foo');
tree = sd.shallowRender(React.createElement(TextEditor, { id: field, initialValue: fieldInput, onSubmit: callbackFunction }));
instance = tree.getMountedInstance();
vdom = tree.getRenderOutput();
});
it('testing-render-description', function() {
// some tests
});
})
Whenever we use skin-deep we are using it on components where we also use shallowRender. I was wondering if anyone has a good understanding of what skin-deep is really doing? I've been searching all morning for a good description of its functionality and purpose but am yet to find a satisfying answer.
EDIT: Moved some logic to the beforeEach to be more descriptive with my problem
Thanks!