I am weak on testing and never formed a good testing methodology. My knowledge of common Java/JS testing frameworks is also thin, so I need a lot of learning and practice.
I recently read a great article about testing techniques in JUnit. I translated it here to understand it better.
Original link: Click here

When we look at JUnit tests, sometimes they feel strange. We must mock objects and results, which takes a lot of work. Although we now have many advanced tools and frameworks like Mockito and PowerMock, the code written with them is sometimes not as readable, understandable, or maintainable as we would like.
Structure test cases
Here is a simple strategy to make JUnit tests readable without side effects.
Split tests into three parts using simple comments: Given, When, Then. You might think a blog post for such a simple sentence is overkill, but in practice we often get lost without this structure.
The code below is an example (simpler than real projects). But this structure helps you write better tests.
/**
* If an item is loaded from the repository, the name of that item should
* be transformed into uppercase.
*/
@Test
public void shouldReturnItemNameInUpperCase() {
//
// Given
//
Item mockedItem = new Item("it1", "Item 1", "This is item 1", 2000, true);
when(itemRepository.findById("it1")).thenReturn(mockedItem);
//
// When
//
String result = itemService.getItemNameUpperCase("it1");
//
// Then
//
verify(itemRepository, times(1)).findById("it1");
assertThat(result, is("ITEM 1"));
The purpose of each block is obvious. Let’s summarize.
Given
This part sets up the mocked return values or input parameters. Mock methods are prepared here. In unit tests, this is usually the longest and most complex part.
Note: Mockito’s when is part of the Given phase. It is about preparing the test, so it belongs here.
When
This is where you call the method under test. This part is usually the shortest.
Then
This is where you assert results and verify method calls. The checks happen here.
Naming test cases
Early test methods often used the test prefix. That’s no longer common. Some people like underscores; I prefer camelCase.
A method name should carry a lot of information, but often comments inside the test explain it better. Names like shouldReturnItemNameInUpperCase() are clear. At the beginning of a project, it’s good to agree on a naming convention.
Summary
That is the article. A few more personal thoughts: Preparing large amounts of data for tests is painful. When multiple test cases need the same mocks, create helpers or builders to reuse them. Of course, as shared mocks grow, they can become complex and require more tests themselves. So you need to weigh tradeoffs when creating and reusing mock data.
Final Thoughts
The translation is straightforward, but as the author says, practice is where we often get lost. I will add some of my own thoughts as well.
- Underscore naming We use underscore naming for frontend JS/TS projects and backend Java projects. The pattern is usually should_xxx_when_xxx_given_xxx. It is readable and maps directly to then/when/given in the test case.
- Use utility classes for common mock data For complex data, we use JSON files and deserialize them for reuse. But if many test cases depend on one dataset, changing it can break many tests. It is a balancing act. Frontend and backend both use builders to provide basic data for test cases.
- Given-When-Then applies to both frontend and backend tests. It is about structuring tests, not limited to JUnit. The specific syntax may differ, but internalize the concept.

