Mastering Unit Testing: Practical Tips, Common Pitfalls, and Best Practices
This article explores how to effectively use unit testing in daily development, defining its purpose, debunking common misconceptions, presenting the AIR principles, offering coverage level guidelines, and sharing practical tips, code examples, and solutions for handling mocks, static classes, and integration challenges.
The author combines daily work experience to discuss how to make the most of unit testing.
Preface
Learning unit testing should go beyond the technical layer—frameworks and mocking libraries—because the goal is to maximize the return on time invested while minimizing effort, which is not easy.
Definition of Unit Testing
Unit testing is the verification and validation of the smallest testable parts of software. In Java, a "unit" often refers to a class.
In plain language, unit testing validates the correctness of a class, distinct from integration or system testing, and is a developer‑led, minimal‑scale test.
Key Statistics
85% of defects originate during the design phase.
The later a bug is discovered, the exponentially higher its fixing cost.
Therefore, writing unit tests significantly impacts delivery quality and labor cost.
Common Pitfalls
Wasting Time and Slowing Development
Test effort must be balanced with code lifecycle, debugging ability, and review time. Without proper unit tests, code becomes hard to maintain.
Testing Should Be a Developer’s Responsibility
Developers, being most familiar with the code, should write unit tests during design to increase confidence and reduce downstream testing issues.
Ignoring Legacy Code
Writing unit tests for old code forces deeper understanding and improves code quality; tests should be added during refactoring.
How to Write Good Unit Tests
AIR Principle
The tests should be Automatic , Independent , and Repeatable , like air—imperceptible yet essential.
My interpretation:
Automate execution via CI, use assertions instead of prints, and avoid manual intervention.
Ensure each test is independent; no ordering or shared state.
Mock external dependencies (databases, middleware) so tests are environment‑agnostic.
Coverage Guidelines
Statement coverage should reach 70%; core modules require 100% statement and branch coverage. – Alibaba Java Development Manual
Coverage levels:
Level 1: Normal flow works with correct inputs.
Level 2: Invalid inputs raise logical exceptions, not system crashes.
Level 3: Edge cases and boundary data are tested.
Level 4: All branches and loops are exercised.
Level 5: Every field of complex output data is verified.
In practice, achieving 95%+ coverage demands testing many branches and exception paths, but diminishing returns apply; unnecessary tests (e.g., trivial getters) can be excluded.
Practical Example
public ApiResponse<List<Long>> getInitingSolution() {
List<Long> solutionIdList = new ArrayList<>();
SolutionListParam solutionListParam = new SolutionListParam();
solutionListParam.setSolutionType(SolutionType.GRAPH);
solutionListParam.setStatus(SolutionStatus.INIT_PENDING);
solutionListParam.setStartId(0L);
solutionListParam.setPageSize(100);
List<OperatingPlan> operatingPlanList = operatingPlanMapper.queryOperatingPlanListByType(solutionListParam);
for (; !CollectionUtils.isEmpty(operatingPlanList);) {
// do something
solutionListParam.setStartId(operatingPlanList.get(operatingPlanList.size() - 1).getId());
operatingPlanList = operatingPlanMapper.queryOperatingPlanListByType(solutionListParam);
}
return ResponsePackUtils.packSuccessResult(solutionIdList);
}When testing, mock the database query and handle the hidden boundary where the loop runs only once for >100 records.
Mocking Time
Use Mockito to mock Date objects: when(date.getTime()).thenReturn(time). For static Calendar.getInstance(), employ PowerMock or Mockito 4.x to mock static methods.
@RunWith(PowerMockRunner.class)
@PrepareForTest({Calendar.class, ImpServiceTest.class})
public class ImpServiceTest {
@InjectMocks
private ImpService impService = new ImpServiceImpl();
@Before
public void setup(){
MockitoAnnotations.initMocks(this);
Calendar now = Calendar.getInstance();
now.set(2022, Calendar.JULY, 2, 0, 0, 0);
PowerMockito.mockStatic(Calendar.class);
PowerMockito.when(Calendar.getInstance()).thenReturn(now);
}
}Testing Final/Static Classes
Static or final classes require Mockito 4.x or PowerMock; version compatibility must be verified to avoid NoSuchMethodError.
Handling External Dependencies (e.g., Tair, MetaQ)
Use @RunWith(PandoraBootRunner.class) to start the Pandora container, or mock the SDK classes directly with PowerMock.
@RunWith(PowerMockRunner.class)
@PrepareForTest({DataEntry.class})
public class MockTair {
@Mock
private DataEntry dataEntry;
@Before
public void hack() throws Exception {
PowerMockito.whenNew(DataEntry.class).withNoArguments().thenReturn(dataEntry);
}
@Test
public void mock() throws Exception {
String value = "value";
PowerMockito.when(dataEntry.getValue()).thenReturn(value);
DataEntry tairEntry = new DataEntry();
Assert.assertEquals(value, tairEntry.getValue());
}
}Using IoC for Test Isolation
Inject dependencies so static utility classes can be mocked, reducing coupling between services and helpers.
@Service
public class LoginServiceImpl implements LoginService {
public Boolean login(String username, String password, String ip) {
if (!IpUtil.verify(ip)) {
return false;
}
return true;
}
}Mock IpUtil in tests to isolate LoginServiceImpl.
Avoid Testing Trivial Code
Skip unit tests for generated getters/setters or toString methods; exclude such packages from CI coverage.
Testing Void Methods
Verify side effects on the database using an embedded H2 database.
Use verify(mock, times(1)).method() to ensure interactions.
Mock exceptions with doThrow and assert expected behavior.
References:
https://scottming.github.io/2021/04/07/unit-testing/
https://docs.spring.io/spring-framework/docs/current/reference/html/testing.html#integration-testing
https://yuque.antfin-inc.com/fangqintao.fqt/pu2ycr/eabim6
https://yuque.antfin-inc.com/aone613114/en7p02/pdtwmb
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Alibaba Cloud Developer
Alibaba's official tech channel, featuring all of its technology innovations.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
