Flutter Engine
The Flutter Engine
Classes | Public Member Functions | List of all members
io.flutter.embedding.android.FlutterAndroidComponentTest Class Reference

Public Member Functions

void pluginsReceiveFlutterPluginBinding ()
 
void activityAwarePluginsReceiveActivityBinding ()
 
void normalLifecycleStepsDoNotTriggerADetachFromFlutterEngine ()
 
void twoOverlappingFlutterActivitiesDoNotCrosstalk ()
 

Detailed Description

Definition at line 49 of file FlutterAndroidComponentTest.java.

Member Function Documentation

◆ activityAwarePluginsReceiveActivityBinding()

void io.flutter.embedding.android.FlutterAndroidComponentTest.activityAwarePluginsReceiveActivityBinding ( )
inline

Definition at line 107 of file FlutterAndroidComponentTest.java.

107 {
108 // ---- Test setup ----
109 // Place a FlutterEngine in the static cache.
110 FlutterLoader mockFlutterLoader = mock(FlutterLoader.class);
111 FlutterJNI mockFlutterJni = mock(FlutterJNI.class);
112 when(mockFlutterJni.isAttached()).thenReturn(true);
113 FlutterEngine cachedEngine = spy(new FlutterEngine(ctx, mockFlutterLoader, mockFlutterJni));
114 FlutterEngineCache.getInstance().put("my_flutter_engine", cachedEngine);
115
116 // Add mock plugin.
117 FlutterPlugin mockPlugin =
118 mock(FlutterPlugin.class, withSettings().extraInterfaces(ActivityAware.class));
119 ActivityAware activityAwarePlugin = (ActivityAware) mockPlugin;
120 ActivityPluginBinding.OnSaveInstanceStateListener mockSaveStateListener =
121 mock(ActivityPluginBinding.OnSaveInstanceStateListener.class);
122
123 // Add a OnSaveStateListener when the Activity plugin binding is made available.
124 doAnswer(
125 new Answer() {
126 @Override
127 public Object answer(InvocationOnMock invocation) throws Throwable {
128 ActivityPluginBinding binding =
129 (ActivityPluginBinding) invocation.getArguments()[0];
130 binding.addOnSaveStateListener(mockSaveStateListener);
131 return null;
132 }
133 })
134 .when(activityAwarePlugin)
135 .onAttachedToActivity(any(ActivityPluginBinding.class));
136
137 cachedEngine.getPlugins().add(mockPlugin);
138
139 // Create a fake Host, which is required by the delegate.
140 FlutterActivityAndFragmentDelegate.Host fakeHost = new FakeHost(cachedEngine);
141
142 FlutterActivityAndFragmentDelegate delegate = new FlutterActivityAndFragmentDelegate(fakeHost);
143
144 // --- Execute the behavior under test ---
145 // Push the delegate through all lifecycle methods all the way to destruction.
146 delegate.onAttach(ctx);
147
148 // Verify plugin was given an ActivityPluginBinding.
149 ArgumentCaptor<ActivityPluginBinding> pluginBindingCaptor =
150 ArgumentCaptor.forClass(ActivityPluginBinding.class);
151 verify(activityAwarePlugin, times(1)).onAttachedToActivity(pluginBindingCaptor.capture());
152 ActivityPluginBinding binding = pluginBindingCaptor.getValue();
153 assertNotNull(binding.getActivity());
154 assertNotNull(binding.getLifecycle());
155
156 delegate.onRestoreInstanceState(null);
157
158 // Verify that after Activity creation, the plugin was allowed to restore state.
159 verify(mockSaveStateListener, times(1)).onRestoreInstanceState(isNull());
160
161 delegate.onCreateView(null, null, null, 0, true);
162 delegate.onStart();
163 delegate.onResume();
164 delegate.onPause();
165 delegate.onStop();
166 delegate.onSaveInstanceState(mock(Bundle.class));
167
168 // Verify that the plugin was allowed to save state.
169 verify(mockSaveStateListener, times(1)).onSaveInstanceState(any(Bundle.class));
170
171 delegate.onDestroyView();
172 delegate.onDetach();
173
174 // Verify that the plugin was detached from the Activity.
175 verify(activityAwarePlugin, times(1)).onDetachedFromActivity();
176 }
static SkISize times(const SkISize &size, float factor)
SIT bool any(const Vec< 1, T > &x)
Definition: SkVx.h:530

◆ normalLifecycleStepsDoNotTriggerADetachFromFlutterEngine()

void io.flutter.embedding.android.FlutterAndroidComponentTest.normalLifecycleStepsDoNotTriggerADetachFromFlutterEngine ( )
inline

Definition at line 179 of file FlutterAndroidComponentTest.java.

179 {
180 // ---- Test setup ----
181 // Place a FlutterEngine in the static cache.
182 FlutterLoader mockFlutterLoader = mock(FlutterLoader.class);
183 FlutterJNI mockFlutterJni = mock(FlutterJNI.class);
184 when(mockFlutterJni.isAttached()).thenReturn(true);
185 FlutterEngine cachedEngine = spy(new FlutterEngine(ctx, mockFlutterLoader, mockFlutterJni));
186 FlutterEngineCache.getInstance().put("my_flutter_engine", cachedEngine);
187
188 // Create a fake Host, which is required by the delegate.
189 FakeHost fakeHost = new FakeHost(cachedEngine);
190
191 // Create the real object that we're testing.
192 FlutterActivityAndFragmentDelegate delegate =
193 spy(new FlutterActivityAndFragmentDelegate(fakeHost));
194
195 // --- Execute the behavior under test ---
196 // Push the delegate through all lifecycle methods all the way to destruction.
197 delegate.onAttach(ctx);
198 delegate.onRestoreInstanceState(null);
199 delegate.onCreateView(null, null, null, 0, true);
200 delegate.onStart();
201 delegate.onResume();
202 delegate.onPause();
203 delegate.onStop();
204 delegate.onDestroyView();
205 delegate.onDetach();
206
207 verify(delegate, never()).detachFromFlutterEngine();
208 }

◆ pluginsReceiveFlutterPluginBinding()

void io.flutter.embedding.android.FlutterAndroidComponentTest.pluginsReceiveFlutterPluginBinding ( )
inline

Definition at line 53 of file FlutterAndroidComponentTest.java.

53 {
54 // ---- Test setup ----
55 // Place a FlutterEngine in the static cache.
56 FlutterLoader mockFlutterLoader = mock(FlutterLoader.class);
57 FlutterJNI mockFlutterJni = mock(FlutterJNI.class);
58 when(mockFlutterJni.isAttached()).thenReturn(true);
59 FlutterEngine cachedEngine = spy(new FlutterEngine(ctx, mockFlutterLoader, mockFlutterJni));
60 FlutterEngineCache.getInstance().put("my_flutter_engine", cachedEngine);
61
62 // Add mock plugin.
63 FlutterPlugin mockPlugin = mock(FlutterPlugin.class);
64 cachedEngine.getPlugins().add(mockPlugin);
65
66 // Create a fake Host, which is required by the delegate.
67 FakeHost fakeHost = new FakeHost(cachedEngine);
68 fakeHost.shouldDestroyEngineWithHost = true;
69
70 // Create the real object that we're testing.
71 FlutterActivityAndFragmentDelegate delegate = new FlutterActivityAndFragmentDelegate(fakeHost);
72
73 // --- Execute the behavior under test ---
74 // Push the delegate through all lifecycle methods all the way to destruction.
75 delegate.onAttach(ctx);
76
77 // Verify that the plugin is attached to the FlutterEngine.
78 ArgumentCaptor<FlutterPlugin.FlutterPluginBinding> pluginBindingCaptor =
79 ArgumentCaptor.forClass(FlutterPlugin.FlutterPluginBinding.class);
80 verify(mockPlugin, times(1)).onAttachedToEngine(pluginBindingCaptor.capture());
81 FlutterPlugin.FlutterPluginBinding binding = pluginBindingCaptor.getValue();
82 assertNotNull(binding.getApplicationContext());
83 assertNotNull(binding.getBinaryMessenger());
84 assertNotNull(binding.getTextureRegistry());
85 assertNotNull(binding.getPlatformViewRegistry());
86
87 delegate.onRestoreInstanceState(null);
88 delegate.onCreateView(null, null, null, 0, true);
89 delegate.onStart();
90 delegate.onResume();
91 delegate.onPause();
92 delegate.onStop();
93 delegate.onDestroyView();
94 delegate.onDetach();
95
96 // Verify the plugin was detached from the FlutterEngine.
97 pluginBindingCaptor = ArgumentCaptor.forClass(FlutterPlugin.FlutterPluginBinding.class);
98 verify(mockPlugin, times(1)).onDetachedFromEngine(pluginBindingCaptor.capture());
99 binding = pluginBindingCaptor.getValue();
100 assertNotNull(binding.getApplicationContext());
101 assertNotNull(binding.getBinaryMessenger());
102 assertNotNull(binding.getTextureRegistry());
103 assertNotNull(binding.getPlatformViewRegistry());
104 }

◆ twoOverlappingFlutterActivitiesDoNotCrosstalk()

void io.flutter.embedding.android.FlutterAndroidComponentTest.twoOverlappingFlutterActivitiesDoNotCrosstalk ( )
inline

Definition at line 211 of file FlutterAndroidComponentTest.java.

211 {
212 // ---- Test setup ----
213 // Place a FlutterEngine in the static cache.
214 FlutterLoader mockFlutterLoader = mock(FlutterLoader.class);
215 FlutterJNI mockFlutterJni = mock(FlutterJNI.class);
216 when(mockFlutterJni.isAttached()).thenReturn(true);
217 FlutterEngine cachedEngine = spy(new FlutterEngine(ctx, mockFlutterLoader, mockFlutterJni));
218 FlutterEngineCache.getInstance().put("my_flutter_engine", cachedEngine);
219 LifecycleChannel mockLifecycleChannel = mock(LifecycleChannel.class);
220 when(cachedEngine.getLifecycleChannel()).thenReturn(mockLifecycleChannel);
221
222 Intent intent = FlutterActivity.withCachedEngine("my_flutter_engine").build(ctx);
223 ActivityController<FlutterActivity> activityController1 =
224 Robolectric.buildActivity(FlutterActivity.class, intent);
225 activityController1.create().start().resume();
226
227 InOrder inOrder = inOrder(mockLifecycleChannel);
228 inOrder.verify(mockLifecycleChannel, times(1)).appIsResumed();
229 verifyNoMoreInteractions(mockLifecycleChannel);
230
231 activityController1.pause();
232 // Create a second instance on the same engine and start running it as well.
233 ActivityController<FlutterActivity> activityController2 =
234 Robolectric.buildActivity(FlutterActivity.class, intent);
235 activityController2.create().start().resume();
236
237 // From the onPause of the first activity.
238 inOrder.verify(mockLifecycleChannel, times(1)).appIsInactive();
239 // By creating the second activity, we should automatically detach the first activity.
240 inOrder.verify(mockLifecycleChannel, times(1)).appIsDetached();
241 // In order, the second activity then is resumed.
242 inOrder.verify(mockLifecycleChannel, times(1)).appIsResumed();
243 verifyNoMoreInteractions(mockLifecycleChannel);
244
245 // The first activity goes through the normal lifecycles of destruction, but since we
246 // detached the first activity during the second activity's creation, we should ignore the
247 // first activity's destruction events to avoid crosstalk.
248 activityController1.stop().destroy();
249 verifyNoMoreInteractions(mockLifecycleChannel);
250 }

The documentation for this class was generated from the following file: