Test Class and Method
I know many would be unhappy seeing classes, but classes are only used to decorate and organize code, you can always do more functional things with Web Atoms Unit Tests.
/** Category decorator is optional, it just lets you specify name of test instead of name of class that extends TestItem */
@Category("Test Case 1")
export default class TestCase1 extends TestItem {
@Test
public parseTest() {
Assert.equals(2, parseInt("2", 10));
}
/** You can specify name of test */
@Test("Parse Float Test")
public parseFloat() {
Assert.equals(2.5, parseFloat("2.5"));
}
}
How to run the test?
You can execute @web-atoms/unit-test/index.js
script against folder of all scripts. You can also give path to single test file as well.
d:\git\test> node ./node_modules/@web-atoms/unit-test/index.js ./dist
Test Case 1 > parseTest success.
Test Case 1 > Parse Float Test success.
Async Tests
Your test method can also return Promise and it unit test engine will await for the result.
@Category("Async Test 1")
export default class TestCase1 extends TestItem {
@Test
public async asyncTestOne() {
const p = method that returns Promise ....
await p;
}
}
Global Separation
Each unit test executes in a separate Global
context in Node, this isolates every unit test method. Even same test methods in same class do not share same context.
declare var global: any;
export default class TestCase1 extends TestItem {
@Test
public async parseTest() {
global.a = 1;
await Atom.delay(100);
Assert.equal(1, global.a);
}
@Test
public async parseTest2() {
global.a = 2;
await Atom.delay(50);
Assert.equal(2, global.a);
}
}
Both tests will be successful.
How to test ViewModel?
Since AtomViewModel requires dependency injection, we have created a class AtomTest
which sets up dependency injection with Mock Service Container.
This class contains app
and it has a method waitForPendingCalls
which allows you to wait for all pending initializations.
class TestVM extends AtomViewModel {
public movies: IMovie[];
public search: string = null;
@Inject private movieService: MovieService;
/** This will be executed when vm is initialized and it will
* be executed when search will be updated
*/
@Load({ init: true, watch: true })
public async loadItems(ct: CancelToken) {
const s = this.search;
this.movies = await this.movieService.loadMovies(s, ct);
}
}
export default class TestVMCase extends AtomTest {
@Test
public async vmTest() {
// this waits till loading of vm is complete
const vm = await this.createViewModel(TestVM);
Assert.equals(5, vm.movies.length);
// lets update search
vm.search = "a";
// lets wait for few milliseconds
// and we assume that mock will populate
// results...
await Atom.delay(100);
Assert.equals(1, vm.movies.length);
}
}
Mocks
Every dependency can specify mock
as shown below.
@DISingleton({ mock: "./mocks/MockMovieService" })
export default class MovieService extends BaseService {
@Get("/api/movies")
public async loadMovies(
@Query("search") search: string,
ct: CancelToken) {
return null;
}
}
./Mocks/MockMovieService
export default class MockMovieService {
public async loadMovies(
search: string,
ct: CancelToken) {
// create artificial delay...
await Atom.delay(1);
if (ct.cancelled) throw new Error("cancelled");
return [
... movies
];
}
}
Top comments (0)