@Override
    public final boolean offerToSnapshot(@Nonnull Object key, @Nonnull Object value) {
        if (snapshotEdge == null) {
            throw new IllegalStateException("Outbox does not have snapshot queue");
        }
        if (shouldBlock()) {
            return false;
        }

        assert unfinishedSnapshotKey == null || unfinishedSnapshotKey.equals(key)
                : "Different key offered after previous call returned false: expected="
                + unfinishedSnapshotKey + ", got=" + key;
        assert unfinishedSnapshotValue == null || unfinishedSnapshotValue.equals(value)
                : "Different value offered after previous call returned false: expected="
                + unfinishedSnapshotValue + ", got=" + value;

        // pendingSnapshotEntry is used to avoid duplicate serialization when the queue rejects the entry
        if (pendingSnapshotEntry == null) {
            // We serialize the key and value immediately to effectively clone them,
            // so the caller can modify them right after they are accepted by this method.
            Data sKey = serializationService.toData(key);
            Data sValue = serializationService.toData(value);
            pendingSnapshotEntry = entry(sKey, sValue);
        }

        boolean success = offerInternal(snapshotEdge, pendingSnapshotEntry);
        if (success) {
            pendingSnapshotEntry = null;
            unfinishedSnapshotKey = null;
            unfinishedSnapshotValue = null;
        } else {
            unfinishedSnapshotKey = key;
            unfinishedSnapshotValue = value;
        }
        return success;
    }
@Test
    public void when_offer3FailsAndDifferentItemOffered_then_fail() {
        do_when_offerDifferent_then_fail(e -> outbox.offerToSnapshot(e, e));
    }