How to write an unit test with AAA pattern
AAA pattern is a common approach used in unit testing to structure the tests and make them more organized and readable. The triple A contains Arrange, Act, and Assert.
Arrange
In this step, you set up the initial conditions for your test. This involves creating any objects, initializing any variables, and configuring any dependencies that your test requires. Essentially, you are arranging the elements that your test will act upon.
Act
This step involves actually executing the code that you want to test. This may involve calling a method or function, passing in some arguments, and obtaining the result.
Assert
Finally, in this step, you verify that the output of the code under test matches what you expected. This may involve checking values of variables or properties, comparing expected and actual results, or ensuring that certain conditions are met.
TS Examples
Here’s an example of using the AAA pattern in TypeScript to test a function that adds two numbers:
function addNumbers(x: number, y: number): number {
return x + y;
}
describe('addNumbers', () => {
it('should add two numbers correctly', () => {
// Arrange
const x = 2;
const y = 3;
// Act
const result = addNumbers(x, y);
// Assert
expect(result).toEqual(5);
});
});
In this TypeScript example, we have a function addNumbers()
that takes two number parameters and returns their sum. We use the describe() and it()
functions provided by a testing library (such as Jest or Mocha) to define a test suite and a test case respectively. Inside the test case, we follow the AAA pattern:
- Arrange: We set up the values of x and y that we want to test with.
- Act: We call the
addNumbers()
function with the values of x and y, and store the result in result. - Assert: We use the
expect()
function provided by the testing library to check that the value of result is equal to the expected value of 5.
React Example
Here is an example of using the AAA pattern in a unit test for a React component written in TypeScript. The component being tested is called ItemList
, which takes an array of Item
objects as a prop and renders them as a list of <li>
elements.
Component file - ItemList.tsx
export interface Item {
id: number;
name: string;
}
export interface Props {
items: Item[];
}
function ItemList({ items }: Props): JSX.Element {
return (
<ul>
{items.map((item) => (
<li key={item.id}>{item.name}</li>
))}
</ul>
);
}
Test File - ItemList.test.tsx
import { render, screen } from '@testing-library/react';
import ItemList, { Item } from './ItemList';
describe('ItemList', () => {
it('should render a list of items correctly', () => {
// Arrange
const items: Item[] = [
{ id: 1, name: 'Item 1' },
{ id: 2, name: 'Item 2' },
{ id: 3, name: 'Item 3' }
];
// Act
render(<ItemList items={items} />);
const itemElements = screen.getAllByRole('listitem');
// Assert
expect(itemElements).toHaveLength(3);
expect(itemElements[0]).toHaveTextContent('Item 1');
});
});
Here’s how the AAA pattern is used in unit test above:
Arrange: In this step, we set up the initial conditions for the test. In this case, we create an array of
Item
objects that we want to render in the list.Act: This step involves actually rendering the component under test and obtaining any elements that we want to make assertions on. In this case, we use the
render()
function provided by the@testing-library/react
library to render the ItemList component with the items prop we created in the Arrange step. Then, we use thegetAllByRole()
function to get all of the<li>
elements rendered by the component and store them in theitemElements
variable.Assert: Finally, in this step, we verify that the output of the component under test matches what we expected. In this case, we use the expect() function provided by the testing library to check that the itemElements array has a length of 3 (since we passed in 3 Item objects), and that the first item element has the correct text content (“Item 1”).
By following the AAA pattern, we can write clear and readable tests that are easy to understand and maintain.