Classes + Testing
Objective
- ECMAScript modules (ESM).
- Classes, constructors, and inheritance.
- Fields, methods, and encapsulation.
- Static fields and methods.
- Abstract classes and methods?
- JavaScript Object Notation (JSON) for serialization and deserialization.
- Unit testing using Mocha (opens in a new tab) and Chai (opens in a new tab).
1 Modules
Build a simple banking application that manages accounts and provides various operations such as depositing to, withdrawing from, adding, removing, and retrieving accounts.
-
Initialize your directory as a package using
npm init
, then set the module format to ESM inpackage.json
:{ "type": "module" }
. -
Create a
Bank
module,bank.js
, where you declare an array,accounts
, of object literals to store the following accounts:id
balance
type
08a45dd424 502.30 Savings a9e2465841 4,100.00 Current 7160dca601 34,420.55 Current 2efde49d9d 61,023.69 Savings -
Implement and export the following functions in the
Bank
module:-
add(account)
adds either aSavings
orCurrent
account to the array of accounts and returns its identifier.The identifier is generated using the Nano ID (opens in a new tab) (
nanoid
(opens in a new tab)) package. -
getAll()
return all accounts. -
get(id)
returns an account by identifier. -
remove(id)
deletes an account by identifier. -
deposit(id, amount)
adds the amount to the account balance. -
withdraw(id, amount)
subtracts the amount from the account balance, if it has sufficient balance. -
totalBalance()
returns the total balance for all accounts. -
deductFee(fee)
deducts a monthly fee from the balance of allCurrent
accounts. -
distributeBenefit(percentage)
increases the balance of allSavings
accounts by a benefit percentage. -
toJSON()
returns the array of accounts as a JSON string. -
fromJSON(json)
parses the JSON string and returns an array of accounts.
-
-
Write an application,
app.js
, to test theBank
module by creating a couple ofCurrent
andSavings
accounts, then performing a few deposits and withdrawals:- Charge a monthly fee of
10
. - Display the total balance of all accounts after charging the monthly fee.
- Distribute a
6%
benefit. - Display the total balance of all accounts after distributing the benefit.
- Display the list of accounts in JSON format.
- Charge a monthly fee of
2 Classes
Classes in JavaScript are, for the most part, syntactic sugar for prototype-based inheritance (opens in a new tab).
Rewrite the application from 1 Modules using the classes Bank
, BankAccount
, CurrentAccount
, and SavingsAccount
, as specified in the UML diagram, where a Bank
is composed of multiple BankAccount
s and each BankAccount
is either a CurrentAccount
or a SavingsAccount
.
Complete the 3 Exceptions guide to learn more about throwing and catching exceptions.
3 Unit Testing
Install the Mocha Test Explorer (opens in a new tab) and the ES6 Mocha Snippets (opens in a new tab) extensions for Visual Studio Code.
Mocha (opens in a new tab) is a test framework that supports test-driven development (TDD) by providing a simple interface for writing and running tests. Mocha tests run serially, allowing for flexible and accurate reporting, while mapping uncaught exceptions to the correct test cases.
Chai (opens in a new tab) is an assertion library that can follow a test-driven or behavior-driven
development (BDD), can be
paired with any testing framework, and supports plugins such as
chai-superagent
(opens in a new tab) and
sinon-chai
(opens in a new tab).
There are numerous testing tools, frameworks, and libraries listed under Links → Testing.
-
Install the
convert
(opens in a new tab) package usingnpm install convert
, then import and use is to convert a few units:index.jsimport convert from "convert"; console.log("360 s = %d m", convert(360, "seconds").to("minutes")); console.log("5 km = %f mi", convert(5, "kilometers").to("nautical miles")); console.log("12 lb = %d oz", convert(12, "pounds").to("ounces")); console.log("8,192 B = %d KiB", convert(8192, "bytes").to("KiB")); console.log("10 atm = %f kPa", convert(10, "atmospheres").to("kPa")); console.log("451 °F = %f °C", convert(451, "fahrenheit").to("celsius"));
-
Install Mocha (opens in a new tab) as local development dependency:
npm install --save-dev mocha
-
Create a
test/convert.spec.js
test specification file, that usesmocha
andassert
, to test some of the unit conversions provided byconvert
:test/convert.spec.jsimport convert from "convert"; import assert from "assert"; describe("convert", function () { describe("time", function () { it("should convert 60 s to 1 m", function () { assert.equal(convert(60, "seconds").to("minutes"), 1); }); it("should convert 1h to 3,600 s", function () { assert.equal(convert(1, "hours").to("seconds"), 3600); }); }); describe("mass", function () { it("should convert 1 kg to 2.2 lb", function () { assert.equal(convert(1, "kg").to("pounds"), 2.2); }); }); });
-
Run the tests using
npx mocha
and fix the failing test case usingNumber.toFixed()
(opens in a new tab). -
Add a script to
package.json
to run the tests usingnpm test
:package.json{ "scripts": { "test": "mocha" } }
-
Install Chai (opens in a new tab) as a local development dependency:
npm install --save-dev chai
-
Rewrite the test assertions in a BDD-style using
chai.expect()
(opens in a new tab):test/convert.spec.jsimport convert from "convert"; import { describe, it } from "mocha"; import { expect } from "chai"; describe("convert", function () { describe("time", function () { it("should convert 60 s to 1 m", function () { expect(convert(60, "seconds").to("minutes")).to.be.equal(1); }); it("should convert 1 h to 3600 s", function () { expect(convert(1, "hours").to("seconds")).to.be.equal(3600); }); }); describe("mass", function () { it("should convert 1 kg to 2.2 lb", function () { expect(convert(1, "kg").to("pounds")).to.be.equal(2.2); }); }); describe("best", function () { it("should convert to best with unit and quantity properties", function () { expect(convert(1500, "meters").to("best")).to.have.own.property( "unit", ); expect(convert(1500, "meters").to("best")).to.have.own.property( "quantity", ); }); }); });
-
Write unit tests, using Mocha + Chai, for each method of the
Bank
class and run them.
Resources
- MDN: Using classes (opens in a new tab), Working with objects (opens in a new tab), Keyed collections (opens in a new tab), Inheritance and the prototype chain (opens in a new tab), JavaScript modules (opens in a new tab), Classes (opens in a new tab),
new.target
(opens in a new tab),constructor
(opens in a new tab) - Comparing the best Node.js unit testing frameworks (opens in a new tab)
- Testing frameworks for Node.js (opens in a new tab)
- Eloquent JavaScript | The Secret Life of Objects (opens in a new tab)
- ES modules: A cartoon deep-dive (opens in a new tab)
- TDD vs BDD vs ATDD: Key Differences (opens in a new tab)