1.7 Testing
In our testing environment we can use any testing engine in this example we use mixture of moca / sinon / chai.
Unit testing
Unit testing is meant to test any singe unit of your application and our dependency injection which is inspired by Angular 2 gives you possibility to do so:
import {Injector, Router, Request} from "typeix";
import {assert, use} from "chai";
import * as sinonChai from "sinon-chai";
import {spy, assert as assertSpy} from "sinon";
import {HomeController} from "../../controllers/home";
import {Assets} from "../../components/assets";
import {TemplateEngine} from "../../components/mu2";
// use chai spies
use(sinonChai);
describe("Home controller", () => {
let controller: HomeController;
let assetsMock = {};
let requestMock = {
redirectTo: () => {}
};
let routerMock = {
createUrl: () => {}
};
let templateMock = {};
before(() => {
let injector = Injector.createAndResolve(HomeController, [
{
provide: Assets,
useValue: assetsMock
},
{
provide: Request,
useValue: requestMock
},
{
provide: Router,
useValue: routerMock
},
{
provide: TemplateEngine,
useValue: templateMock
}
]);
controller = injector.get(HomeController);
});
it("Should test redirect action", (done) => {
let aSpy = spy(requestMock, "redirectTo");
let bSpy = spy(routerMock, "createUrl");
controller.redirect().then(() => {
assertSpy.called(aSpy);
assertSpy.called(bSpy);
done();
}).catch(done);
});
});
Integration testing
Integration testing provides you nice api where you can startup fake server and execute any route and result is an FakeResponseApi which gives you access to request body which is usually sent do client and response headers, status code.
FakeResponseApi
export interface FakeResponseApi {
getStatusCode(): number;
getBody(): string | Buffer;
getHeaders(): any;
}
Integration test
import {fakeHttpServer, FakeServerApi} from "typeix";
import {assert, use} from "chai";
import * as sinonChai from "sinon-chai";
import {spy, assert as assertSpy} from "sinon";
import {Application} from "../../application";
// use chai spies
use(sinonChai);
describe("Home controller", () => {
var server: FakeServerApi;
before(() => {
server = fakeHttpServer(Application);
});
function template(title, name, id) {
return `<!DOCTYPE html>\n<html lang="en">\n<head>\n <meta charset="UTF-8">\n <title>${title}</title>\n</head>\n<body>\n<h4>Headline: ${name}</h4>\n<p>\n Action id: ${id} name: ${name} <- Before each core <- Before cache controller filter <-null;\n</p>\n</body>\n</html>\n`;
};
it("Should test index action", (done) => {
server.GET("/").then(data => {
assert.equal(data.getBody(), template("Home page example", "this is home page", "NO_ID"));
done();
}).catch(done);
});
it("Should test home id action", (done) => {
server.GET("/100/whatevericansee").then(data => {
assert.equal(data.getBody(), template("Template engine with typeix", "whatevericansee", "100"));
done();
}).catch(done);
});
});
Example of package.json
{
"name": "demo-app",
"version": "0.0.1",
"scripts": {
"test:unit": "npm run compile && mocha build/tests/unit/ --debug --full-trace",
"test:intergration": "npm run compile && mocha build/tests/intergration/ --debug --full-trace",
"test": "npm run test:intergration && npm run test:unit",
"compile": "tsc -p tsconfig.json",
"demo": "npm run compile && node build/bootstrap.js",
"start": "npm run demo"
},
"devDependencies": {
"@types/chai": "^3.4.34",
"@types/mocha": "^2.2.32",
"@types/node": "^7.0.16",
"@types/sinon": "^2.1.3",
"@types/sinon-chai": "^2.7.27",
"@types/mu2": "0.0.29",
"chai": "^3.5.0",
"mocha": "^3.0.2",
"sinon": "^2.1.0",
"sinon-chai": "^2.8.0",
"typescript": "^2.3.0"
},
"dependencies": {
"mime": "^1.3.4",
"mu2": "^0.5.21",
"typeix": "^1.0.0-beta.21"
}
}