@Test
    public void testUpdateAffiliationTwice() throws Exception
    {
        // Setup test fixture.
        final CachingPubsubPersistenceProvider provider = new CachingPubsubPersistenceProvider();
        final Node mockNode = Mockito.mock(Node.class);
        Mockito.lenient().when(mockNode.getUniqueIdentifier()).thenReturn(new Node.UniqueIdentifier("mock-service-1", "mock-node-a"));
        final JID affiliateAddress = new JID("test-user-1", "example.org", null);
        final NodeAffiliate firstAffiliate = new NodeAffiliate(mockNode, affiliateAddress);
        final NodeAffiliate.Affiliation firstAffiliation = NodeAffiliate.Affiliation.publisher;
        firstAffiliate.setAffiliation(firstAffiliation);
        final NodeAffiliate secondAffiliate = new NodeAffiliate(mockNode, affiliateAddress);
        final NodeAffiliate.Affiliation secondAffiliation = NodeAffiliate.Affiliation.outcast;
        secondAffiliate.setAffiliation(secondAffiliation);

        // Execute system under test.
        provider.updateAffiliation(mockNode, firstAffiliate);
        provider.updateAffiliation(mockNode, secondAffiliate);

        // Verify results.
        final List<CachingPubsubPersistenceProvider.NodeOperation> pending = provider.nodesToProcess.computeIfAbsent(mockNode.getUniqueIdentifier(), id -> new ArrayList<>());
        assertEquals(1, pending.size());

        final CachingPubsubPersistenceProvider.NodeOperation nodeOperation = pending.get(0);
        assertEquals(mockNode.getUniqueIdentifier(), nodeOperation.node.getUniqueIdentifier());
        assertEquals(CachingPubsubPersistenceProvider.NodeOperation.Action.UPDATE_AFFILIATION, nodeOperation.action);
        assertEquals(affiliateAddress, nodeOperation.affiliate.getJID());
        assertEquals(secondAffiliation, nodeOperation.affiliate.getAffiliation()); // must match that of the last invocation.
        assertNull(nodeOperation.subscription);

        assertEquals(0, provider.itemsPending.size());
        assertEquals(0, provider.itemsToAdd.size());
        assertEquals(0, provider.itemsToDelete.size());
    }
Executes a test that, through {@link CachingPubsubPersistenceProvider#updateAffiliation(Node, NodeAffiliate)}
attempts to update the same affiliation (with the same user and same node) 'twice'.

Updates of an affiliation are never partial. This allows the caching provider to optimize two sequential updates.

Therefor, this test asserts that after each invocation, only one operation, corresponding to the last update, is
scheduled.
xmppserver/src/test/java/org/jivesoftware/openfire/pubsub/CachingPubsubPersistenceProviderAffiliationOperationsTest.java