AsyncStorageModule extends ReactContextBaseJavaModule implements ModuleDataCleaner.Cleanable { @ReactMethod public void multiMerge(final ReadableArray keyValueArray, final Callback callback) { new GuardedAsyncTask<Void, Void>(getReactApplicationContext()) { @Override protected void doInBackgroundGuarded(Void... params) { if (!ensureDatabase()) { callback.invoke(AsyncStorageErrorUtil.getDBError(null)); return; } WritableMap error = null; try { mReactDatabaseSupplier.get().beginTransaction(); for (int idx = 0; idx < keyValueArray.size(); idx++) { if (keyValueArray.getArray(idx).size() != 2) { error = AsyncStorageErrorUtil.getInvalidValueError(null); return; } if (keyValueArray.getArray(idx).getString(0) == null) { error = AsyncStorageErrorUtil.getInvalidKeyError(null); return; } if (keyValueArray.getArray(idx).getString(1) == null) { error = AsyncStorageErrorUtil.getInvalidValueError(null); return; } if (!AsyncLocalStorageUtil.mergeImpl( mReactDatabaseSupplier.get(), keyValueArray.getArray(idx).getString(0), keyValueArray.getArray(idx).getString(1))) { error = AsyncStorageErrorUtil.getDBError(null); return; } } mReactDatabaseSupplier.get().setTransactionSuccessful(); } catch (Exception e) { FLog.w(ReactConstants.TAG, e.getMessage(), e); error = AsyncStorageErrorUtil.getError(null, e.getMessage()); } finally { try { mReactDatabaseSupplier.get().endTransaction(); } catch (Exception e) { FLog.w(ReactConstants.TAG, e.getMessage(), e); if (error == null) { error = AsyncStorageErrorUtil.getError(null, e.getMessage()); } } } if (error != null) { callback.invoke(error); } else { callback.invoke(); } } }.execute(); } AsyncStorageModule(ReactApplicationContext reactContext); @Override String getName(); @Override void initialize(); @Override void onCatalystInstanceDestroy(); @Override void clearSensitiveData(); @ReactMethod void multiGet(final ReadableArray keys, final Callback callback); @ReactMethod void multiSet(final ReadableArray keyValueArray, final Callback callback); @ReactMethod void multiRemove(final ReadableArray keys, final Callback callback); @ReactMethod void multiMerge(final ReadableArray keyValueArray, final Callback callback); @ReactMethod void clear(final Callback callback); @ReactMethod void getAllKeys(final Callback callback);  }
@Test public void testMultiMerge() throws Exception { final String mergeKey = "mergeTest"; JSONObject value = new JSONObject(); value.put("foo1", "bar1"); value.put("foo2", createJSONArray("val1", "val2", 3)); value.put("foo3", 1001); value.put("foo4", createJSONObject("key1", "randomValueThatWillNeverBeUsed")); mStorage.multiSet(JavaOnlyArray.of(getArray(mergeKey, value.toString())), mock(Callback.class)); { Callback callback = mock(Callback.class); mStorage.multiGet(getArray(mergeKey), callback); Mockito.verify(callback, Mockito.times(1)) .invoke(null, JavaOnlyArray.of(getArray(mergeKey, value.toString()))); } value.put("foo1", 1001); value.put("foo2", createJSONObject("key1", "val1")); value.put("foo3", "bar1"); value.put("foo4", createJSONArray("val1", "val2", 3)); JSONObject newValue = new JSONObject(); newValue.put("foo2", createJSONObject("key2", "val2")); JSONObject newValue2 = new JSONObject(); newValue2.put("foo2", createJSONObject("key1", "val3")); mStorage.multiMerge( JavaOnlyArray.of( JavaOnlyArray.of(mergeKey, value.toString()), JavaOnlyArray.of(mergeKey, newValue.toString()), JavaOnlyArray.of(mergeKey, newValue2.toString())), mock(Callback.class)); value.put("foo2", createJSONObject("key1", "val3", "key2", "val2")); Callback callback = mock(Callback.class); mStorage.multiGet(getArray(mergeKey), callback); Mockito.verify(callback, Mockito.times(1)) .invoke(null, JavaOnlyArray.of(getArray(mergeKey, value.toString()))); }