Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

6 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Flutter Unit Testing Catalog

A catalog of unit testing patterns for Flutter and Dart, structured in the spirit of the Gang of Four Design Patterns.

Introduction → · Catalog Index ↓ · Glossary →

Every entry is a self-contained chapter with prose and runnable Dart tests. Pick a pattern below, or read the introduction first.


Catalog Index

Click any chapter to open its pattern — prose, production code, and tests.

Foundations

# Chapter
Introduction: The Message Metaphor

Core Message Patterns

# Chapter Subject
1 Receiving a Message and Responding MessageFormatter — relative-time labels, message previews
2 Changing State UnreadCounter — badge on a conversation row
3 Sending Out More Messages ChatManager.sendMessage calling analytics
4 Side Effects — Completeness of Outgoing Calls ChatManager.sendMessage — persist, observe, log

Reliability Patterns

# Chapter Subject
5 Exceptions & Error Handling Nine error-handling patterns (E1–E9) on ChatManager
E1: Exception Throwing
E2: Exception Types
E3: Error Messages
E4: Exception Handling
E5: State After Exception
E6: Fallback Mechanisms
E7: Input Validation
E8: Boundary Conditions
E9: Resource Cleanup
6 Adversarial Inputs ChatManager.receiveMessage — out-of-order timestamps
7 Initial State and Setup ChatManager loading message history
8 Concurrency and Timing Concurrent sends + delivery receipts
9 Idempotence Dedup by stable clientMessageId

Specialized Patterns

# Chapter Subject
10 Memory and Resource Management IncomingMessageBinder — stream subscriptions
11 Third-Party Integration ChatService wrapping a backend HTTP client
12 Fallbacks and Redundancies MessageRepository — remote + cache + placeholder
13 Performance and Timing TypingIndicator — debounced "stopped typing"
14 Security and Input Validation MessageSanitizer — HTML/null-byte stripping
15 State Transitions MessageDelivery lifecycle

All chapters share the same imagined chat app as their running example, so the catalog reads as one story. Each chapter's code/ folder is self-contained — no cross-chapter imports required.


The Idea Behind This Book

Every method call is a message. An object receives a message, does something with it, and the world changes — or does not. Three things can happen when a method is called: it can return a value, it can change internal state, or it can send messages to other objects. Everything in unit testing flows from these three primitives.

This catalog names each pattern, explains the problem that arises without it, and shows you the solution in Flutter/Dart — production class first, test second. Like the Gang of Four, each entry stands alone. Read them in order or jump to what you need from the Catalog Index above.


How to Read This Catalog

Every chapter follows the same GoF-inspired structure. If you encounter a term you do not recognise, the Glossary defines every key word used in this catalog.

Section Purpose
Intent One sentence: what this test pattern verifies
The Problem The scenario that hurts without this pattern
Forces The tensions you are navigating
Solution The pattern in prose, followed by Dart code
Consequences What you gain and what you give up
Implementation Notes Dart/flutter_test-specific tips
Related Patterns Other entries in this catalog

Code for each chapter lives in its code/ subfolder — a production .dart file and a _test.dart file side by side.


Running the Code

This catalog is a Flutter package. The test files live alongside the production code inside each chapter's code/ folder rather than in a top-level test/ directory, so flutter test needs to be pointed at them explicitly.

To run every test in the catalog:

flutter pub get
flutter test $(find . -name "*_test.dart" -not -path "*/build/*")

To run a single chapter's tests:

flutter test chapter01_receiving_responding/code/message_formatter_test.dart

Dependencies are declared in pubspec.yaml. Run flutter pub get once before running tests.


What This Catalog Deliberately Does Not Cover

The patterns in this book are scoped to unit tests for plain Dart classes — the layer where business logic lives. Several adjacent categories of testing are intentionally outside that scope. They are not less important; they answer different questions and use different oracles. Naming them here is meant to set expectations, not to dismiss them.

  • Widget tests (testWidgets) — Tests that mount a widget tree in a simulated rendering environment and verify layout, tap behavior, or accessibility. Every test() call in this catalog operates on a plain class; nothing renders on screen. For the widget layer, see the Flutter widget testing documentation.

  • Golden / snapshot tests — Pixel-level regression tests for rendered widgets. The oracle is an image comparison, not an expect() matcher. These belong in the same suite as widget tests and require the same rendering pipeline.

  • Integration tests (integration_test package) — End-to-end tests that drive a real app on a device or emulator. They verify that the assembled application behaves correctly, not that any individual class fulfills its contract. The patterns in this catalog are about the second question; integration tests answer the first.

  • Property-based testing (e.g. glados) — Generative testing where the framework fabricates inputs to find counterexamples. Complementary rather than excluded: every pattern here could be reinforced with a property-based test. The catalog uses example-based assertions throughout because they are the form most teams write first and most reliably.

  • Test-first vs test-last workflow — Whether tests are written before, after, or alongside production code is a workflow choice. The patterns work regardless. The Introduction discusses this briefly; this catalog takes no position.

  • State-management framework testing (bloc / riverpod / provider / GetX) — Testing notifiers, blocs, and providers requires conventions specific to each framework (e.g. bloc_test's blocTest() helper, ProviderContainer for Riverpod). The general patterns here apply to the classes those frameworks wrap, but framework-specific helpers are not covered.

  • Mocking libraries (mocktail, mockito) — Every test in this catalog hand-writes its stubs and mocks to keep the seam visible. In a real codebase, mocktail removes most of the boilerplate. The patterns translate directly; the syntax changes.


Exception Sub-Catalog Quick Reference

Chapter 5 is itself a mini-catalog. The nine entries in the Catalog Index cover every aspect of testing error handling:

Entry What It Tests Read
E1 That an exception is thrown at all
E2 That the correct exception type is thrown
E3 That the exception carries the correct message
E4 That the calling code handles the exception correctly
E5 That the object is in a consistent state after an exception
E6 That a fallback path is taken when the primary path fails
E7 That invalid inputs are rejected before reaching business logic
E8 That the system behaves correctly at boundary values
E9 That resources are released even when an exception occurs

Unsure how E7 differs from E8? See validation vs boundaries.


Reference

  • Catalog Index — All chapters and patterns
  • Glossary — Definitions for every key term: stub, mock, fake, spy, SUT, observable behavior, and more.
  • License — Free to use and share. If you publish a book or similar work derived from this catalog, credit the original (name + link).
  • Social media assets — Share images for GitHub, Twitter/X, LinkedIn, and square posts

If your classes have hard-coded dependencies and you are not sure how to make them testable before applying the patterns, see Designing for Testability.

About

A GoF-style catalog of unit testing patterns for Flutter and Dart — prose, examples, and 116 runnable tests.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages