Definition

Unit Testing

Testing individual functions, methods, or components in isolation from the rest of the system.

Full Definition

Unit testing is the practice of testing the smallest testable parts of a software application — individual functions, methods, or classes — in complete isolation from their dependencies. Each unit test verifies that a single piece of code behaves correctly given specific inputs, without relying on databases, network calls, file systems, or other external systems. Unit tests form the foundation of the testing pyramid and are typically written by developers as part of the development process itself.


Characteristics of effective unit tests:
  • Fast: Execute in milliseconds. A suite of thousands of unit tests should complete in seconds, not minutes.
  • Isolated: Test one thing at a time with all dependencies mocked or stubbed. A unit test failure should point to exactly one piece of code.
  • Repeatable: Produce the same result every time, regardless of environment, order of execution, or time of day.
  • Self-Validating: Automatically determine pass or fail — no manual inspection of output required.
  • Timely: Written alongside or before the code they test (in TDD, they're written first).


What unit tests typically cover:
  • Pure business logic and calculations
  • Input validation and boundary conditions
  • Error handling and exception paths
  • State transitions and data transformations
  • Edge cases: null values, empty strings, maximum values, negative numbers


Common unit testing frameworks:
  • JavaScript/TypeScript: Jest, Vitest, Mocha
  • Java: JUnit, TestNG
  • Python: pytest, unittest
  • C#: NUnit, xUnit, MSTest
  • Go: built-in testing package
  • Ruby: RSpec, Minitest


The role of mocking in unit testing:

Since unit tests must run in isolation, dependencies are replaced with test doubles:

  • Mocks: Verify that the code under test interacts with dependencies correctly (e.g., "did it call the email service?")
  • Stubs: Provide predetermined responses to method calls (e.g., "when the database is queried, return this user object")
  • Fakes: Lightweight implementations of dependencies (e.g., an in-memory database instead of a real one)


Common mistakes in unit testing:

The most prevalent error is testing implementation details instead of behavior. A unit test that verifies the internal structure of a function — which private methods it calls, in what order — becomes brittle and breaks whenever the code is refactored, even if the behavior doesn't change. Test the inputs and outputs, not the internal wiring. Another mistake is writing tests that are too tightly coupled to mocks, leading to tests that pass even when the real integration would fail. Over-mocking gives false confidence. Teams also frequently write unit tests that are too large, testing multiple behaviors in a single test — when it fails, you can't tell which behavior broke without debugging.


Best practices:
  • Follow the Arrange-Act-Assert (AAA) pattern: set up the test state, perform the action, verify the result
  • Name tests descriptively: calculateTax_withZeroAmount_returnsZero is better than testCalculateTax3
  • Aim for high coverage of critical business logic, but don't chase 100% coverage of trivial code (getters, setters, simple constructors)
  • Keep tests independent — no test should depend on another test's state or execution order
  • Run unit tests on every commit in the CI pipeline as the first quality gate

Examples

  • 1.Testing a calculateDiscount() function with inputs of $100 and 20% discount, asserting the return value is $80 — verifying pure arithmetic logic without any database or API involvement
  • 2.Unit test for a password validation function that checks minimum length (8 chars), requires at least one uppercase letter, one number, and one special character — testing each rule independently with passing and failing inputs
  • 3.Testing an email formatter utility that takes a user object and returns a formatted greeting string — mocking the user object to control inputs and asserting the exact output string matches the expected template
  • 4.Unit test verifying that a date parsing function correctly handles ISO 8601 format, Unix timestamps, and relative dates ("3 days ago"), and throws a clear error for unrecognized formats
  • 5.Testing a shopping cart's addItem method to verify it correctly updates the total, increments the item count, and handles the edge case of adding a duplicate item by increasing quantity rather than adding a new line

In BesTest

BesTest complements unit testing by managing the higher-level manual and functional test cases that sit above unit tests in the testing pyramid. While unit tests run in CI/CD pipelines, BesTest tracks the integration, system, and acceptance tests that require manual execution or human verification. The coverage dashboard provides a unified view across all testing levels.

See Unit Testing in Action

Experience professional test management with BesTest. Free for up to 10 users.

Try BesTest Free