### Question:
FabricUIManager implements UIManager, JSHandler { @DoNotStrip public synchronized void completeRoot(int rootTag, @Nullable List<ReactShadowNode> childList) { SystraceMessage.beginSection( Systrace.TRACE_TAG_REACT_JAVA_BRIDGE, "FabricUIManager.completeRoot") .flush(); try { long startTime = SystemClock.uptimeMillis(); childList = childList == null ? new LinkedList<ReactShadowNode>() : childList; if (DEBUG) { FLog.d(TAG, "completeRoot rootTag: " + rootTag + ", childList: " + childList); } ReactShadowNode currentRootShadowNode = getRootNode(rootTag); Assertions.assertNotNull( currentRootShadowNode, "Root view with tag " + rootTag + " must be added before completeRoot is called"); currentRootShadowNode = calculateDiffingAndCreateNewRootNode(currentRootShadowNode, childList); if (DEBUG) { FLog.d( TAG, "ReactShadowNodeHierarchy after diffing: " + currentRootShadowNode.getHierarchyInfo()); } applyUpdatesRecursive(currentRootShadowNode); mUIViewOperationQueue.dispatchViewUpdates( mCurrentBatch++, startTime, mLastCalculateLayoutTime); mRootShadowNodeRegistry.replaceNode(currentRootShadowNode); } catch (Exception e) { handleException(getRootNode(rootTag), e); } finally{ Systrace.endSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE); } } FabricUIManager(
      ReactApplicationContext reactContext,
      ViewManagerRegistry viewManagerRegistry,
      JavaScriptContextHolder jsContext,
      EventDispatcher eventDispatcher); void setBinding(FabricBinding binding); @Nullable @DoNotStrip ReactShadowNode createNode(
      int reactTag, String viewName, int rootTag, ReadableNativeMap props, long eventTarget); @Nullable @DoNotStrip ReactShadowNode cloneNode(ReactShadowNode node); @Nullable @DoNotStrip ReactShadowNode cloneNodeWithNewChildren(ReactShadowNode node); @Nullable @DoNotStrip ReactShadowNode cloneNodeWithNewProps(
      ReactShadowNode node, @Nullable ReadableNativeMap newProps); @Nullable @DoNotStrip ReactShadowNode cloneNodeWithNewChildrenAndProps(
      ReactShadowNode node, ReadableNativeMap newProps); @Nullable @DoNotStrip void appendChild(ReactShadowNode parent, ReactShadowNode child); @DoNotStrip List<ReactShadowNode> createChildSet(int rootTag); @DoNotStrip void appendChildToSet(List<ReactShadowNode> childList, ReactShadowNode child); @DoNotStrip synchronized void completeRoot(int rootTag, @Nullable List<ReactShadowNode> childList); void dispatchCommand(int reactTag, int commandId, @Nullable ReadableArray commandArgs); @Override @DoNotStrip int addRootView(
      final T rootView); @Override @DoNotStrip synchronized void updateRootLayoutSpecs(int rootViewTag, int widthMeasureSpec, int heightMeasureSpec); void removeRootView(int rootTag); @Nullable @DoNotStrip long getEventTarget(int reactTag); @DoNotStrip void registerEventHandler(long eventHandlerPointer); @DoNotStrip void releaseEventTarget(long eventTargetPointer); @DoNotStrip void releaseEventHandler(long eventHandlerPointer); @Override @DoNotStrip void invoke(long eventTarget, String name, WritableMap params); @Override void setJSResponder(int reactTag, boolean blockNativeResponder); @Override void clearJSResponder(); @Override void initialize(); @Override void onCatalystInstanceDestroy(); @Override void profileNextBatch(); @Override Map<String, Long> getPerformanceCounters();  }### Answer:
@Test(expected = AssertionError.class) public void testCompleteRootBeforeAddRoot() { mFabricUIManager.completeRoot(0, new ArrayList<ReactShadowNode>()); }
@Test public void testCompleteRoot() { ReactRootView rootView = new ReactRootView(RuntimeEnvironment.application.getApplicationContext()); int rootTag = mFabricUIManager.addRootView(rootView); List<ReactShadowNode> children = mFabricUIManager.createChildSet(rootTag); mFabricUIManager.completeRoot(rootTag, children); }