How to test functions with Architest

Ralaivao Andry
2 min readApr 24, 2024
Archikoder Lens Class structure preview

This is a more advanced question about the particular way to test plain function with the framework ArchiTest. For an introduction to ArchiTest, read this article

The question was brought by a colleague that was testing the framework. It goes like this: “If the unit of tests are classes and methods, how do i test my already written plain functions that compose my application?”

The answer is that you can’t directly test your functions with ArchiTest as the main motivation to use the framework is to improve your code by leveraging the power of OOP.

Nevertheless, you still can adapt ArchiTest to test your functions like this.

The functions to be tested

As an example, you have the next Util.ts file that exports your functions and you want to write tests for.

import jwt, { Secret } from "jsonwebtoken";
import { CustomJwtPayload } from "../../models/JwtInterface";
import { login } from "../DatabaseUtils/DatabaseUtils";

const SECRET = "verySecretkey";

export const extractJwt = (authHeader: string | undefined) => {
if (authHeader && authHeader.startsWith('Bearer ')) {
return authHeader.replace('Bearer ', '')
}
return undefined
}

export const extractLogin = async (token: string) => {
const decodedToken = jwt.verify(token, SECRET as Secret) as CustomJwtPayload
return decodedToken.login
}

Write a class that mirrors you functions

You have to create an alternate class, let’s call it “Util”. For each function you want to test, write an “Util” method that have the same parameters configuration as the function, and return the result of the function call (Without intelliSense, you’ll write those manually)

//...
export class Util{

_extractJwt(authHeader: string | undefined){
return extractJwt(authHeader);
}

_extractLogin(token: string){
return extractLogin(token);
}
}

Write your test class

Finally, write your usual Architest class. (Architest introduction)

//...
export class UtilTest extends Util{

@test
_extractJwt(authHeader = "NotBearer ") {
return undefined;
}

@test
_extractLogin(token = "dskdfjdkf"): Promise<any> {
return Promise.reject("jwt malforme")
}
}

The Cons

Let’s see the cons and the inconveniences if you take this road to write tests for your functions and not refactor the code:

  • We loose intelliSense when writing the intermediate class
  • More complicated codes that are less intuitive; an alternate class that is more difficult to read and make sense.

The Pros

However, here is the pros if you commit to take this path:

  • You are doing the exercise of creating classes, naming them correctly, group similar methods together and separate what should be separated.
  • You can use your alternate classes in your code, slowly moving from a procedural architecture to a more object oriented perspective

Conclusion

ArchiTest is designed to test OOP codes. However, there is still a way to write tests for your procedural functions.

Using ArchiTest can be a way for you to migrate from a procedural to an object oriented approach.

--

--