Unit tests are very useful for checking how our app is working.
Otherwise, we run into all kinds of issues later on.
In this article, we’ll look at some best practices we should follow when writing JavaScript unit tests.
Test Middlewares in Isolation
We should test middleware in isolation so that we can test the critical parts of our app.
Middlewares are used by everything, so we should test them.
Since they’re functions, we can test them in isolation.
We can just invoke it directly.
Also, we can use node-mock-http to spy on the behavior of the middleware.
We can write:
const unitUnderTest = require("./middleware");
const httpMocks = require("node-mocks-http");
test("should return http status 403 when request header is empty", () => {
const request = httpMocks.createRequest({
method: "GET",
url: "/user/1",
headers: {
authentication: ""
}
});
const response = httpMocks.createResponse();
unitUnderTest(request, response);
expect(response.statusCode).toBe(403);
});
We use the node-mocks-http to make our requests.
Then we can pass the request and response objects into our middleware.
And then get the response.
Measure and Refactor Using Static Analysis Tools
We should use static analysis tools to improve our code quality and keep our code maintainable.
It’s useful for detecting duplication, code complexity, and other issues.
We can use tools like Sonarqube and Code Climate to check the statically analyze our app.
Check Our Readiness for Node-Related Chaos
We should also check for issues like when the server or a process dies, or when memory is overloaded.
Speed issues are also important to check.
To regularly free up resources, we can use tools to regularly kill our app instances.
We can do performance testing to find those issues.
APM tools will also help us find them.
Avoid Global Test Fixtures and Seeds
Global test fixtures aren’t good since they’re shared between multiple tests.
We don’t want to share them between multiple tests since we want independent tests.
Tests shouldn’t start with data that have been manipulated by other pieces of code.
Therefore, we should reset the data after each test so that we can always test with clean data.
Our tests should be able to run in any order and still give us the same results.
They also keep our tests simple since they’ll be easier to trace.
For instance, we write something like:
it("should return true if we can log in with valid username and password", async () => {
const username = 'james';
const password = 'password';
await addUser({ username, password });
const result = login(username, password);
expect(result).to.be(true);
});
We create a new user and then use that to log in so that we know the user that we’re testing with exists.
Frontend Testing
Front end testing is also important.
Separate UI from Functionality
We should test UI separately from functionality.
When we’re testing component logic, then UI becomes the noise that should be extracted.
This way, our tests can focus on only manipulating data.
UI can be tested separately.
We can disable animation and only check data in tests.
Conclusion
We can separate our logic tests with our UI tests.
Also, we test middleware in isolation.
Data should also be created from scratch for each test.