Skip to content

Commit 52f8da1

Browse files
committed
docs: add more details to unit test section
1 parent c9829cd commit 52f8da1

File tree

1 file changed

+99
-0
lines changed

1 file changed

+99
-0
lines changed

website/docs/development/testing.mdx

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,3 +85,102 @@ describe('auth methods', async () => {
8585
```
8686

8787
Core concepts to keep in mind when unit testing JS/TS modules with Chai:
88+
89+
#### Stub internal methods to make tests predictable
90+
91+
Functions often make use of internal libraries such as `fs` for reading files and performing operations that are dependent on the overall state of the app (or database/filesystem). Since we're only testing that the given function behaves the way we want, we **stub** these libraries.
92+
93+
For example, here we stub the `fs` library so that "reading" the `proxy.config.json` file returns our mock config file:
94+
95+
```js
96+
// Define the mock config file
97+
const newConfig = JSON.stringify({
98+
authentication: [
99+
{ type: 'local', enabled: true },
100+
{ type: 'ActiveDirectory', enabled: true },
101+
{ type: 'openidconnect', enabled: true },
102+
],
103+
});
104+
105+
// Create the stub for `fs.existsSync` and `fs.readFileSync`
106+
const fsStub = {
107+
existsSync: sinon.stub().returns(true),
108+
readFileSync: sinon.stub().returns(newConfig),
109+
};
110+
```
111+
112+
This stub will make all calls to `fs.existsSync` to return `true` and all calls to `readFileSync` to return the `newConfig` mock file.
113+
114+
Then, we use `proxyquire` to plug in the stub to the library that we're testing:
115+
116+
```js
117+
const config = proxyquire('../src/config', {
118+
fs: fsStub,
119+
});
120+
121+
// Initialize the user config after proxyquiring to load the stubbed config
122+
config.initUserConfig();
123+
```
124+
125+
Finally, when calling the function we're trying to test, the internal calls will automatically resolve to the values we chose.
126+
127+
#### Setup and cleanup
128+
129+
`before` and `beforeEach`, `after` and `afterEach` are testing constructs that allow executing code before and after each test. This allows setting up stubs before each test, making API calls, setting up the database - or otherwise cleaning up the database after test execution.
130+
131+
This is an example from another test file (`test/addRepoTest.test.js`):
132+
133+
```js
134+
before(async function () {
135+
app = await service.start();
136+
137+
await db.deleteRepo('test-repo');
138+
await db.deleteUser('u1');
139+
await db.deleteUser('u2');
140+
await db.createUser('u1', 'abc', 'test@test.com', 'test', true);
141+
await db.createUser('u2', 'abc', 'test2@test.com', 'test', true);
142+
});
143+
144+
// Tests go here
145+
146+
after(async function () {
147+
await service.httpServer.close();
148+
149+
await db.deleteRepo('test-repo');
150+
await db.deleteUser('u1');
151+
await db.deleteUser('u2');
152+
});
153+
```
154+
155+
#### Focus on expected behaviour
156+
157+
Mocha and Chai make it easy to write tests in plain English. It's a good idea to write the expected behaviour in plain English and then prove it by writing the test:
158+
159+
```js
160+
describe('auth methods', async () => {
161+
it('should return a local auth method by default', async function () {
162+
// Test goes here
163+
});
164+
165+
it('should return an error if no auth methods are enabled', async function () {
166+
// Test goes here
167+
});
168+
169+
it('should return an array of enabled auth methods when overridden', async function () {
170+
// Test goes here
171+
});
172+
});
173+
```
174+
175+
Assertions can also be done similarly to plain English:
176+
177+
```js
178+
expect(authMethods).to.have.lengthOf(3);
179+
expect(authMethods[0].type).to.equal('local');
180+
```
181+
182+
#### Unit testing coverage requirement
183+
184+
**All new lines of code introduced in a PR, must have over 80% coverage** (patch coverage). This is enforced by our CI, and generally a PR will not be merged unless this coverage requirement is met. Please make sure to write thorough unit tests to increase GitProxy's code quality!
185+
186+
If test coverage is still insufficient after writing your tests, check out the [CodeCov report](https://app.codecov.io/gh/finos/git-proxy) after making the PR and take a look at which lines are missing coverage.

0 commit comments

Comments
 (0)