How to run single test case when using 'test.concurrent' in Jest? - unit-testing

Update: I checked the issues of Jest again and found this problem has been fixed in v28.0.1. Update to the latest version solved this question.
I write a test file with multiple test cases, and I know how to use test.only or -t to run a "single test case" - as Jest's document and other answers said.
But I notice that when I use test.concurrent, it seems the test cases in the test file are actually run by Jest, and Jest only ignores the result of other test cases.
For example when I run the test below:
describe('Describe', () => {
test.concurrent('test case 1', async () => {
await console.log(1);
});
test.concurrent('test case 2', async () => {
await console.log(2);
});
test.concurrent('test case 3', async () => {
await console.log(3);
});
test.concurrent('test case 4', async () => {
await console.log(4);
});
});
Run:
jest --verbose "--testNamePattern=^Describe test case 1$" --runTestsByPath cuncurrent.test.ts
All the console.log are executed, but when I use test instead of test.current:
describe('Describe', () => {
test('test case 1', async () => {
await console.log(1);
});
test('test case 2', async () => {
await console.log(2);
});
test('test case 3', async () => {
await console.log(3);
});
test('test case 4', async () => {
await console.log(4);
});
});
Only console.log(1) is executed.
Is there anyway to use test.concurrent and run single test case in a test file?

Related

Flutter/Dart slow unit tests: each file taking >4s to start running

My one test file with 7 empty tests is taking 5+ seconds to start running. I've used both flutter test and the Dart test runner in VS Code, and they both take about the same amount of time.
My whole test suite of ~150 tests takes over 30 seconds to complete, because each test file is taking 3-7 seconds just to start running.
launch.json (for Dart test runner)
{
"name": "Dart: Run all tests",
"type": "dart",
"request": "launch",
"program": "./test/"
},
Timed test run:
00:05 +1 -7: Some tests failed.
real 0m9.532s
user 0m0.075s
sys 0m0.138s
I am using nested group blocks, but I don't believe this should cause such an enormous delay that makes TDD extremely slow
Example section of code
void main() {
group('AuthCubit:', () {
late AuthCubit authCubit;
late MockLogIn logIn;
late MockLogOut logOut;
late MockRestoreSession restoreSession;
setUp(() {
logIn = MockLogIn();
logOut = MockLogOut();
restoreSession= MockRestoreSession();
authCubit = AuthCubit(
logIn : logIn,
logOut : logOut,
restoreSession: restoreSession,
);
});
tearDown(() {
authCubit.close();
});
test('initial state is unauthenticated', () async {
expect(authCubit.state, equals(const AuthStateUnauthenticated()));
});
group('logIn():', () {
//? Create late variables that all stages use, if needed
setUp(() {});
//? Create subgroups for stages this function will step through
group('On failure:', () {
setUp(() {});
test('emits unauthenticated state', () async { throw UnimplementedError(); });
});
group('On success:', () {
setUp(() {});
test('emits authenticated state', () async { throw UnimplementedError(); });
});
});
});
// ... + similar empty tests for other functions ...
}
I've tried even testing two empty example test files both separately and combined (see below code) both take 4+ seconds to run individually. If I combine both test files into one file, the execution time is the almost the same as just one test.
The problem seems to be around launching each test file, not the tests themselves.
Tests
test_test_1.dart
import 'package:flutter_test/flutter_test.dart';
//? Create Mocks, Fakes, etc, if needed
void main() {
group('Test File 1:', () {
//? Create late variables that all functions use, if needed
test('empty test 1', () async { throw UnimplementedError(); });
test('empty test 2', () async { throw UnimplementedError(); });
test('empty test 3', () async { throw UnimplementedError(); });
test('empty test 4', () async { throw UnimplementedError(); });
test('empty test 5', () async { throw UnimplementedError(); });
});
}
test_test_2.dart
import 'package:flutter_test/flutter_test.dart';
//? Create Mocks, Fakes, etc, if needed
void main() {
group('Test File 2:', () {
//? Create late variables that all functions use, if needed
test('empty test 1', () async { throw UnimplementedError(); });
test('empty test 2', () async { throw UnimplementedError(); });
test('empty test 3', () async { throw UnimplementedError(); });
test('empty test 4', () async { throw UnimplementedError(); });
test('empty test 5', () async { throw UnimplementedError(); });
});
}
test_test_1_2.dart
import 'package:flutter_test/flutter_test.dart';
//? Create Mocks, Fakes, etc, if needed
void main() {
group('Test File 1:', () {
//? Create late variables that all functions use, if needed
test('empty test 1', () async { throw UnimplementedError(); });
test('empty test 2', () async { throw UnimplementedError(); });
test('empty test 3', () async { throw UnimplementedError(); });
test('empty test 4', () async { throw UnimplementedError(); });
test('empty test 5', () async { throw UnimplementedError(); });
});
group('Test File 2:', () {
//? Create late variables that all functions use, if needed
test('empty test 1', () async { throw UnimplementedError(); });
test('empty test 2', () async { throw UnimplementedError(); });
test('empty test 3', () async { throw UnimplementedError(); });
test('empty test 4', () async { throw UnimplementedError(); });
test('empty test 5', () async { throw UnimplementedError(); });
});
}
Results
test_test_1.dart individual result
00:04 +0 -5: Some tests failed.
real 0m8.743s
user 0m0.060s
sys 0m0.167s
`test_test_2.dart` individual result
00:05 +0 -5: Some tests failed.
real 0m8.982s
user 0m0.137s
sys 0m0.106s
`test_test_1_2.dart` individual result
00:04 +0 -10: Some tests failed.
real 0m8.602s << Note this is actually FASTER than the smaller test files
user 0m0.045s << same ^
sys 0m0.200s
All 3 test file results (in one run)
00:08 +0 -20: Some tests failed.
real 0m12.696s
user 0m0.015s << Weirdly, this is the smallest value out of all test cases
sys 0m0.152s
Questions
What could be the issue with my code, setup (software or hardware), with Dart/Flutter, or anything else?
Pretend I know nothing about Flutter, Dart, or VS Code; what questions would help find the potential causes and solutions for this?
jensjoha on GitHub helped me find a workaround to this by creating "nested aggregate test files"
On a higher level note I should probably add that for each file you have tests in, running tests are going to be slower because it has to do a compile, launch a new process etc. Similarly - as we saw - getting to the point where it actually starts doing something with the tests takes quite a while, so running flutter test specificfile.dart (at least for many specific files) isn't great.
As somewhat of a workaround - when you want to run all tests - you could try to create one test file like done in #86722 (comment) and only run that.
Example
// test_group_1_test.dart
import test_file_1_test.dart as testFile1;
import test_file_2_test.dart as testFile2;
// ...
void main() {
group("test file 1", testFile1.main);
group("test file 2", testFile2.main);
// ...
}
// everything_test.dart
import test_group_1_test.dart as testGroup1
import test_group_2_test.dart as testGroup2
// ...
void main() {
group("test group 1", testGroup1.main);
group("test group 2", testGroup2.main);
// ...
}
With this structure, I can run all (or any group of) test files within the same time it takes to run a single test file, which for my case is ~75% faster.

Check if a stubbed getter function has been called with sinon spy

I am using firebase admin and I am trying to write some unit tests for my code.
Since admin is injected in my function I figured I could mock a very simple object like this:
admin = {
get auth () {
return {
updateUser: () => {
return true;
},
createUser: () => {
return true;
},
getUser: () => {
throw Error('no user');
}
};
}
};
Then in a particular test I can stub the functions. Here is what I have done so far:
// stubbed functions
sinon.stub(admin, 'auth').get(() => () => ({
updateUser: () => ({ called: true }),
getUser: () => (userRecord),
createUser: () => ({ called: false })
}));
and those are working fine (I can see with my logs).
However in my test I would also want to check if createUser has been called at all.
I thought I could set up a spy on the createUser function, but so far I can't really get it to work.
Here is what I have been trying (with a bunch of variation always failing):
it.only('should update a user', async () => {
const userRecord = mockData
sinon.stub(admin, 'auth').get(() => () => ({
updateUser: () => ({ called: true }),
getUser: () => (userRecord),
createUser: () => ({ called: false })
}));
const spy = sinon.spy(admin, 'auth', ['get']); // this is not working
const user = await upsertUser(data, firestore, admin);
expect(user).toEqual(data.userDataForAuth); // this one is ok
sinon.assert.calledOnce(spy.get); // this throws an error
});
the bit of code I am trying to test (which is the upsert function is this:
// in my test exisiting user is not null (the stub `getUser` is returning a object
if (existingUser != null) {
try {
await admin.auth().updateUser(uid, userDataForAuth);
return userDataForAuth;
} catch (error) {
console.log('error', error);
throw Error('error updating user');
}
}
I am not even sure this is the best approach, happy to change it if there is a better one!

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();
});

confirm() click simulation "yes or no" in vue jest

I have to make a test for a vue instance using jest and the test includes a confirm pop up, question is how to simulate click on "Yes" in the pop up. I was trying to use:
window.confirm = jest.fn(() => true);
and:
window.confirm = () => true;
and inventing something like that:
wrapper.confirm = () => true;
But no luck, maybe someone had similar problem?
Since we're running the tests in Nodejs we can reference confirm as global.confirm and If we want to test the function add if it adds 2 whenever confirm returns true we can do this:
const add = require('./add');
describe('add', () => {
describe('confirm returning true', () => {
let result;
beforeAll(() => {
// we define confirm to be a function that returns true
global.confirm = jest.fn(() => true);
result = add(1);
});
it('should call confirm with a string', () => {
expect(global.confirm).toHaveBeenCalledWith(
expect.any(String),
);
});
it('should add two', () => {
expect(result).toBe(3);
});
});
describe('confirm returning false', () => {
let result;
beforeAll(() => {
// we define confirm to be a function that returns false
global.confirm = jest.fn(() => false);
result = add(1);
});
it('should call confirm with a string', () => {
expect(global.confirm).toHaveBeenCalledWith(
expect.any(String),
);
});
it('should NOT add two', () => {
expect(result).toBe(1);
});
});
});
online working example

async call to component.create() does not return

I'm trying to get a jasmine test to run in Karma for an Aurelia project that will require custom configuration of the startup configuration.
Here is the test
it("dreams to be a plugin", async () => {
const component = StageComponent.withResources();
component.configure = (aurelia) => {
return aurelia.use.standardConfiguration();
};
await component.create(bootstrap);
expect(true).toBeTruthy();
});
Unfortunately the test fails, because the call to component.create() does not return, and jasmine times out and fails the test.
Here is a repo that shows the issue.
What am I missing ?
Does component.create() return a Promise? async/await should work if it's a Promise.
it("should support async/await tests", async () => {
let flag = false;
flag = await asyncSetFlagToTrue();
expect(flag).toBeTruthy();
});
function asyncSetFlagToTrue() {
return new Promise(resolve => {
setTimeout(() => {
resolve(true);
}, 1000);
});
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/jasmine/3.0.0/jasmine.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/jasmine/3.0.0/jasmine.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jasmine/3.0.0/jasmine-html.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jasmine/3.0.0/boot.min.js"></script>
Update
I cloned from GitHub and added two tests to component-tester.spec.ts. Both passed.
it('should test async call using done', (done) => {
component.configure = (aurelia) => {
return aurelia.use.standardConfiguration();
};
component.create(bootstrap).then(() => done());
expect(true).toBeTruthy();
});
it('should test async call using async/await', async () => {
component.configure = (aurelia) => {
return aurelia.use.standardConfiguration();
};
await component.create(bootstrap);
expect(true).toBeTruthy();
});