How to find out why a function passed the test in Jest? - unit-testing

Is there a way to show why tested function can pass?
When I follow Jest test Async Code section
It says:
Be sure to return the promise - if you omit this return statement,
your test will complete before fetchData completes.
And my code is:
function add1(n) {
return new Promise((res, rej)=>{
res(n+1)
})
}
test('should add 1', function() {
expect.assertions(1)
//////////////////////////// I did not use RETURN here
add1(10).then((n11)=>{
expect(n11).toBe(11)
})
});
This still passed, I want to know how this can pass?

The Promise resolves immediately and synchronously so the then gets called immediately and the expect has run before the test finishes. (then callbacks run immediately if the Promise has already resolved)
If you use setTimeout to keep the Promise from resolving immediately and synchronously then the test fails unless you return the Promise:
function add1(n) {
return new Promise((res, rej) => {
setTimeout(() => { res(n + 1) }, 0); // use setTimeout
})
}
test('should add 1', function () {
expect.assertions(1)
// PASSES only if Promise is returned
return add1(10).then((n11) => {
expect(n11).toBe(11);
})
});

Related

How can I test a function that use a promise?

how can I test a function that call a promise ?
click() {
this.todoService.getUsers().then(
(resp) => {
this.users = resp;
},
(reject) => {
console.log(reject);
}
);
}
I tried this , but the console return undeefined
it('should get all users', () => {
const users =[....]
todoServiceSpy.getUsers.and.returnValue(of(users).toPromise());
component.click();
console.log('component.users', component.users);
expect(component.users).toEqual(users);
I'm new in testings
You can use async/fixture.whenStable() to wait for the promises in queue to complete before proceeding.
// add async here
it('should get all users', async () => {
const users =[....]
todoServiceSpy.getUsers.and.returnValue(of(users).toPromise());
component.click();
// !! wait for all promises in queue to complete before proceeding
await fixture.whenStable();
console.log('component.users', component.users);
// do assertions
expect(component.users).toEqual(users);
You can also use fakeAsync/tick. I suggest you read up on these methodologies.
It explains some of it here: https://www.digitalocean.com/community/tutorials/angular-testing-async-fakeasync.

How to mock function with callback and return type in Jasmine

I'm trying to mock function that has a stream return type and callback as arg. I get timeout because the call back function never get called.
This is the function I'm trying to test:
public setServerUrls(): Observable<void> {
const obs: Observable<void> = new Observable((observer: Observer<void>) => {
const stream: ClientWritableStream<Util.Server> = this.fileTransferClient.setURLs((error: ServiceError, response) => {
if (error) {
observer.error(`TransferManager Electron: unable to set server urls error: ${error.message}.`);
}
observer.next();
observer.complete();
logger.info(`TransferManager Electron: setting URLs completed.`);
});
const transferRequest = new Util.Server();
transferRequest
.setIp('localhost')
.setTransferport('9092')
.setUuid('4020a522-81fe-4996-b637-0620ae656d29');
stream.write(transferRequest);
stream.end();
});
return obs;
}
My jasmine setup:
const settingStream = {
write: () => { },
end: () => { }
};
const callBack = () => {
return;
};
const f = function (callback: Function): any {
return settingStream;
};
mockFileTransferClient = jasmine.createSpyObj('FileTransferClient', {
subscribe: () => mockFileTransferStream,
uploadFile: () => duplexStream,
setURLs: f(callBack)
});
mockFileTransferClientWrapper.createNewFileTransferClient.and.returnValue(mockFileTransferClient as any);
// Question here... does not work!
mockFileTransferClient.setURLs.and.returnValue(settingStream);
test:
it('should set urls', done => {
transferManager.setServerUrls()
.subscribe(
x => {
expect(x).toBeDefined();
done();
}
);
});
This is Elctron + grpc functionality test.
Test timeout because it never gets into the callback and observable never completes.
I'm not sure how to mock setURLs with return value AND callback.
You have to first mock your setUrls to return a resolved observable.
I think what you need here is to use fakeAsync() functionality as you are dealing with async test. Using Tick with fakeAsync ensures that all pending asynchronous activities will finish. In your case it will wait for setTimeout.
Note that you should also inject the setServerUrls using TestBed.inject...
So I think your tests should look like this
it("should .....", fakeAsync(() => {
// Arrange - mock functions
// Act - Make a call to the function
// Use tick() after making call to the function which will flush your setTimeouts
// Assert
}));
For more information, see the fakeAsync documentation

How to write a unit test with data fetching, that alters data based on respone in vuejs?

I am trying to write a unit test for a function that does an async call, but it doesnt seem to alter the data prop, maybe I am doing something wrong.
Check the code below:
getSomething() {
MyService.getThis().then(
response => {
this.status = true;
}
).catch(error => {})
}
TestCase:
describe('test', () => {
beforeEach(() => {
// To ignore the created hook, but this doesnt work, any idea?
spyOn(CustomerData, 'created');
spyOn(MyService, 'getThis').and.returnValue(Promise.resolve(list));
});
wrapper = shallowMount(MyComponent, {
propsData: {
data: {}
},
});
it('should work', () => {
wrapper.vm.getSomething();
expect(wrapper.vm.status).toBeTruthy();
});
});
}
The status should be true, but it is false, but if I print the value of status in the getSomething() function it is indeed true. I have no idea what the issue can be.
update:
In the test case I wrote
it('should work', async () => {
await wrapper.vm.getSomething();
expect(wrapper.vm.status).toBeTruthy();
}
and this seems to work. Is this a good way to solve it? Would love to hear other solutions.
Also I am very interested if it is possible to ignore the created hook, I havent been able to figure that out yet.
Code that running inside getSomething() is asynchronous. MyService.getThis() returns promise, and its execution takes time, in case if you fetching some data from remote serivce.
So first of all you need to return promise from getSomething()
getSomething() {
return MyService.getThis()
.then(response => { this.status = true; })
.catch(error => {})
}
And inside the test you need to return promise outside, to let jest know that your test is asynchronous.
it('should work', () => {
return wrapper.vm.getSomething().then(() => {
expect(wrapper.vm.status).toBeTruthy();
});
});
Or as you mentioned in the edited part you can use async version:
it('should work', async () => {
await getSomething();
expect(wrapper.vm.status).toBeTruthy();
});

sinon stub error "attempted to wrap undefined property of job as function"

I am trying to use sinon stub to test my function that contains two variables called job and job1. How to give temporary values to them to avoid function values.
In one of the file myFunction.js I have functions like
function testFunction() {
var job = this.win.get.value1 //test
var job1 = this.win.get.value2 // test1
if(job === 'test' && job1 === 'test1') {
return true;
}
return false;
}
and I am trying to test testFunction using karma and I tried to stub two values with my values so it can override the function values
it('should test my function', function(done) {
var stub = sinon.stub('job','job1').values('test','test1');
myFunction.testFunction('test', function(err, decodedPayload) {
decodedPayload.should.equal(true);
done();
});
});
I am getting error "attemted to wrap undefined property of job as function"
First of all you could simplify your testFunction to the following.
function testFunction() {
return this.win.get.value1 === 'test' && this.win.get.value2 === 'test1';
}
There's nothing asynchronous going on here so in your test you don't need to use done().
Sinon's 'stub' documentation suggests you should be using the sandbox feature to stub non-function properties.
It's not clear from your question what your context of 'this' is so I'll assume your tests have instantiated whatever it is you're testing with the name 'myFunction' (which your test implies).
It's also unclear what 'win' and 'get' are so this will assume they are objects.
Don't forget to restore() the sandbox so you don't pollute subsequent tests.
it('should test my function', function() {
var sandbox = sinon.sandbox.create();
sandbox.stub(myFunction, 'win').value({
get: {
value1: 'test',
value2: 'test1',
}
});
myFunction.testFunction().should.equal(true);
sandbox.restore();
});

sinon stub a method that was executed in then call of promise

describe("/test" , ()=> {
// separate class 2
class2 = {
// function that i wanna stub
hi: function () {
return "hi";
}
}
// separate class 1
class1 = {
// function that i have stubbed and tested
method1: function() {
return new Promise((resolve, reject) => {
resolve(num);
})
}
}
// method that i will execute
var parent= function (){
class1.method1().then(()=>{
class2.hi();
})
}
// the test
it("should stub hi method",()=>{
var hiTest = sinon.stub(class2, 'hi').resolves(5);
var method1Test = sinon.stub(class1 , 'method1').resolves(5);
// this start the execution of the promise with then call
parent();
// this works fine and test pass
expect(method1Test.calledOnce.should.be.true);
// this doesn't work although i executed the function
expect(hiTest.calledOnce.should.be.true);
})
})
what i wanna do is test the hi method correctly .. because when i test if the method is executed once or not
although i executed it in the then call of the promise it doesn't show that and it make the calledOnce test fail
The problem here is that you are testing the code as if it is synchronous, when it is not (as you are using Promise).
To be able to test this properly we need to be able to hook onto the promise chain that is started with parentcalling class1.method1.
We can do this by returning the promise that calling class1.method1 returns.
In terms of the test itself, we need to make sure Mocha doesnt end the test while we are waiting for the promises, so we use the done callback parameter to tell Mocha when we think the test is finished.
describe("/test", ()=> {
class2 = {
hi: function () {
return "hi";
}
}
class1 = {
method1: function() {
return new Promise((resolve, reject) => {
resolve(num);
})
}
}
var parent = function (){
return class1.method1().then(()=>{
class2.hi();
})
}
it("should stub hi method", (done)=> {
var hiTest = sinon.stub(class2, 'hi').returns(5);
var method1Test = sinon.stub(class1 , 'method1').resolves(5);
parent().then(() => {
expect(method1Test.calledOnce.should.be.true);
expect(hiTest.calledOnce.should.be.true);
done();
});
})
})