@Test
public void testClientTransaction() throws Exception {

    final DistributedDataStore distributedDataStore = mock(DistributedDataStore.class);
    final ActorUtils context = mock(ActorUtils.class);
    doReturn(context).when(distributedDataStore).getActorUtils();
    doReturn(SchemaContextHelper.full()).when(context).getSchemaContext();
    final DistributedShardFrontend rootShard = new DistributedShardFrontend(distributedDataStore, client, ROOT);
    try (DOMDataTreeProducer producer = shardedDOMDataTree.createProducer(Collections.singletonList(ROOT))) {
        shardedDOMDataTree.registerDataTreeShard(ROOT, rootShard, producer);
    }
    final DataStoreClient outerListClient = mock(DataStoreClient.class);
    final ClientTransaction outerListClientTransaction = mock(ClientTransaction.class);
    final ClientLocalHistory outerListClientHistory = mock(ClientLocalHistory.class);
    final DOMDataTreeWriteCursor outerListCursor = mock(DOMDataTreeWriteCursor.class);
    doNothing().when(outerListCursor).close();
    doNothing().when(outerListCursor).write(any(), any());
    doNothing().when(outerListCursor).merge(any(), any());
    doNothing().when(outerListCursor).delete(any());
    doReturn(outerListCursor).when(outerListClientTransaction).openCursor();
    doReturn(outerListClientTransaction).when(outerListClient).createTransaction();
    doReturn(outerListClientHistory).when(outerListClient).createLocalHistory();
    doReturn(outerListClientTransaction).when(outerListClientHistory).createTransaction();
    doReturn(commitCohort).when(outerListClientTransaction).ready();
    doNothing().when(outerListClientHistory).close();
    doNothing().when(outerListClient).close();
    final DistributedShardFrontend outerListShard = new DistributedShardFrontend(
            distributedDataStore, outerListClient, OUTER_LIST_ID);
    try (DOMDataTreeProducer producer =
                 shardedDOMDataTree.createProducer(Collections.singletonList(OUTER_LIST_ID))) {
        shardedDOMDataTree.registerDataTreeShard(OUTER_LIST_ID, outerListShard, producer);
    }
    final DOMDataTreeProducer producer = shardedDOMDataTree.createProducer(Collections.singletonList(ROOT));
    final DOMDataTreeCursorAwareTransaction tx = producer.createTransaction(false);
    final DOMDataTreeWriteCursor txCursor = tx.createCursor(ROOT);
    assertNotNull(txCursor);
    txCursor.write(TestModel.TEST_PATH.getLastPathArgument(), createCrossShardContainer());
    //check the lower shard got the correct modification
    verify(outerListCursor, times(2)).write(pathArgumentCaptor.capture(), nodeCaptor.capture());
    final List<PathArgument> capturedArgs = pathArgumentCaptor.getAllValues();
    assertEquals(2, capturedArgs.size());
    assertThat(capturedArgs,
        hasItems(new NodeIdentifier(TestModel.ID_QNAME), new NodeIdentifier(TestModel.INNER_LIST_QNAME)));
    final List<NormalizedNode<?, ?>> capturedValues = nodeCaptor.getAllValues();
    assertEquals(2, capturedValues.size());
    assertThat(capturedValues,
        hasItems(ImmutableNodes.leafNode(TestModel.ID_QNAME, 1), createInnerMapNode(1)));
    txCursor.close();
    tx.commit().get();
    verify(commitCohort, times(2)).canCommit();
    verify(commitCohort, times(2)).preCommit();
    verify(commitCohort, times(2)).commit();
}