How to test widget that is instantiated in didUpdateWidget in Flutter?
Interview Questions practice on Codemia
Over 8,000 real interview questions from top companies, searchable by company and role.
Introduction
To test logic inside didUpdateWidget, you must trigger a real widget update on the same State object. In practice that means pumping the widget once, then pumping it again with different constructor values while keeping the widget type and key stable so Flutter reuses the existing state.
What didUpdateWidget Is For
didUpdateWidget runs when Flutter keeps the existing State instance but gives it a new widget configuration from the parent. It does not run because the widget called setState on itself, and it does not run when the old state is destroyed and replaced.
That lifecycle detail shapes the test strategy:
- same widget class,
- same key,
- different incoming properties,
- and a second pump from the test.
If you change the key or change the widget type, Flutter creates a new State object and the old one never receives didUpdateWidget.
Example Widget That Recreates a Controller
Here is a small widget that rebuilds a TextEditingController whenever the label prop changes:
The goal of the test is not merely to prove the widget can rebuild. It is to prove the update path went through didUpdateWidget.
Test by Pumping Twice
The simplest and most reliable pattern is a two-pump test:
The stable key is important because it helps Flutter match the new widget instance to the existing stateful element.
Verify Side Effects, Not Just Pixels
Sometimes the thing instantiated in didUpdateWidget is not directly visible. You may be replacing:
- a stream subscription,
- an animation controller,
- a focus node,
- or a callback binding to an external object.
In that case, assert the observable side effect rather than trying to inspect lifecycle methods directly.
One good pattern is to inject a factory or dependency that your test can observe:
If the widget calls that factory from didUpdateWidget, the test can count calls or inspect the created object. That is often cleaner than exposing private state just to make the test pass.
Keep the Parent-Update Mental Model
It helps to think of didUpdateWidget as a parent-driven event. The parent rebuilds, the framework decides the existing child state can be kept, and then the child receives new widget data.
That means a widget test for didUpdateWidget should mimic a parent rebuild. The second pumpWidget call is your parent rebuilding the subtree with new properties.
If you instead call methods on the state directly, you are no longer testing the lifecycle behavior that matters.
When You Need More Than One pump
If didUpdateWidget starts an animation or async callback, the widget tree may need extra time to settle. In those cases use:
- '
pump()' - '
pump(const Duration(...))' - or
pumpAndSettle()
The exact choice depends on whether the side effect is immediate, frame-based, or asynchronous.
Design for Easier Testing
If testing didUpdateWidget feels awkward, that can be a signal that the widget owns too much replaceable state. Not everything belongs in a lifecycle method. If a child can be rebuilt cheaply from current props inside build, that is often simpler than caching a resource and carefully updating it later.
Lifecycle hooks are appropriate when you truly need to synchronize stateful resources with changing widget configuration.
Common Pitfalls
The most common mistake is changing the key between pumps. That causes Flutter to throw away the old State, so the test never exercises didUpdateWidget.
Another mistake is expecting didUpdateWidget to run after setState inside the same widget. It runs when a parent provides a new widget configuration, not when the state mutates itself.
Developers also often assert only final visible text when the real behavior is a side effect such as resubscribing to a stream. Test the effect that actually proves the lifecycle hook ran.
Finally, if the hook triggers asynchronous work, do not assert too early. Add the extra pump calls needed for the update to complete.
Summary
- Trigger
didUpdateWidgetby pumping the same widget type again with new inputs. - Keep the same key so Flutter reuses the existing
State. - Assert side effects that prove the update path ran, not just generic rebuild behavior.
- Remember that
didUpdateWidgetis parent-driven, not caused by the widget's ownsetState. - If the logic is hard to test, reconsider whether the widget is holding unnecessary mutable state.
Related reading
- How to throttle search based on typing speed in iOS UISearchBar?
- How to toggle a UITextField secure text entry hide password in Swift?
- How to train a tensorflow network using JNI on Android?
- How to transfer some data to another Fragment?
- How to throw a SqlException when needed for mocking and unit testing?
- How to turn off dropout for testing in Tensorflow?
- How to trap on UIViewAlertForUnsatisfiableConstraints?
- How to turn on front flash light programmatically in Android?
.png&w=3840&q=75)
Tackling System Design Interview Problems
A short course that equips you with the skills to approach system design interviews methodically.
Start the free courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
Interview Questions practice on Codemia
Over 8,000 real interview questions from top companies, searchable by company and role.