Complete base implementation of the JSON CacheDataImporterExporter.
Resolves gh-67.
This commit is contained in:
@@ -116,7 +116,7 @@ public abstract class AbstractCacheDataImporterExporter
|
||||
* @see org.springframework.context.ApplicationContext
|
||||
* @see java.util.Optional
|
||||
*/
|
||||
protected Optional<ApplicationContext> getApplicationContext() {
|
||||
public Optional<ApplicationContext> getApplicationContext() {
|
||||
return Optional.ofNullable(this.applicationContext);
|
||||
}
|
||||
|
||||
|
||||
@@ -17,24 +17,34 @@ package org.springframework.geode.data.json;
|
||||
|
||||
import static org.springframework.data.gemfire.util.RuntimeExceptionFactory.newIllegalStateException;
|
||||
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.Writer;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.apache.geode.cache.Region;
|
||||
import org.apache.geode.pdx.JSONFormatter;
|
||||
import org.apache.geode.pdx.PdxInstance;
|
||||
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.io.ResourceLoader;
|
||||
import org.springframework.dao.DataAccessResourceFailureException;
|
||||
import org.springframework.data.gemfire.util.CollectionUtils;
|
||||
import org.springframework.geode.data.AbstractCacheDataImporterExporter;
|
||||
import org.springframework.geode.data.CacheDataExporter;
|
||||
import org.springframework.geode.data.CacheDataImporter;
|
||||
import org.springframework.geode.data.json.converter.JsonToPdxConverter;
|
||||
import org.springframework.geode.data.json.converter.ObjectToJsonConverter;
|
||||
import org.springframework.geode.data.json.support.JSONFormatterJsonToPdxConverter;
|
||||
import org.springframework.geode.data.json.support.JSONFormatterPdxToJsonConverter;
|
||||
import org.springframework.lang.NonNull;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* The {@link JsonCacheDataImporterExporter} class is a {@link CacheDataImporter} and {@link CacheDataExporter}
|
||||
@@ -42,10 +52,15 @@ import org.springframework.util.Assert;
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.apache.geode.cache.Region
|
||||
* @see org.apache.geode.pdx.PdxInstance
|
||||
* @see org.springframework.core.io.ClassPathResource
|
||||
* @see org.springframework.core.io.Resource
|
||||
* @see org.springframework.core.io.ResourceLoader
|
||||
* @see org.springframework.geode.data.AbstractCacheDataImporterExporter
|
||||
* @see org.springframework.geode.data.CacheDataExporter
|
||||
* @see org.springframework.geode.data.CacheDataImporter
|
||||
* @see org.springframework.geode.data.json.converter.JsonToPdxConverter
|
||||
* @see org.springframework.geode.data.json.converter.ObjectToJsonConverter
|
||||
* @see org.springframework.stereotype.Component
|
||||
* @since 1.3.0
|
||||
*/
|
||||
@@ -53,46 +68,154 @@ import org.springframework.util.Assert;
|
||||
@SuppressWarnings("rawtypes")
|
||||
public class JsonCacheDataImporterExporter extends AbstractCacheDataImporterExporter {
|
||||
|
||||
private static final int CONTENT_PREVIEW_LENGTH = 50;
|
||||
private static final int DEFAULT_BUFFER_SIZE = 32768;
|
||||
|
||||
protected static final String CLASSPATH_RESOURCE_PREFIX = ResourceLoader.CLASSPATH_URL_PREFIX;
|
||||
protected static final String FILESYSTEM_RESOURCE_PREFIX = "file://";
|
||||
protected static final String ID_FIELD_NAME = "id";
|
||||
protected static final String RESOURCE_NAME_PATTERN = "data-%s.json";
|
||||
|
||||
private JsonToPdxConverter toPdxConverter = newJsonToPdxConverter();
|
||||
|
||||
private ObjectToJsonConverter toJsonConverter = newObjectToJsonConverter();
|
||||
|
||||
// TODO configure via an SPI
|
||||
private @NonNull JsonToPdxConverter newJsonToPdxConverter() {
|
||||
return new JSONFormatterJsonToPdxConverter();
|
||||
}
|
||||
|
||||
// TODO configure via an SPI
|
||||
private @NonNull ObjectToJsonConverter newObjectToJsonConverter() {
|
||||
return new JSONFormatterPdxToJsonConverter();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a reference to the configured {@link JsonToPdxConverter}.
|
||||
*
|
||||
* @return a reference to the configured {@link JsonToPdxConverter}.
|
||||
* @see org.springframework.geode.data.json.converter.JsonToPdxConverter
|
||||
*/
|
||||
protected @NonNull JsonToPdxConverter getJsonToPdxConverter() {
|
||||
return this.toPdxConverter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a reference to the configured {@link ObjectToJsonConverter}.
|
||||
*
|
||||
* @return a reference to the configured {@link ObjectToJsonConverter}.
|
||||
* @see org.springframework.geode.data.json.converter.ObjectToJsonConverter
|
||||
*/
|
||||
protected @NonNull ObjectToJsonConverter getObjectToJsonConverter() {
|
||||
return this.toJsonConverter;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@NonNull @Override
|
||||
public Region doExportFrom(@NonNull Region region) {
|
||||
|
||||
Assert.notNull(region, "Region must not be null");
|
||||
|
||||
String regionName = region.getName();
|
||||
String json = toJson(region);
|
||||
|
||||
getLogger().debug("Saving JSON [{}] from Region [{}]", json, region.getName());
|
||||
|
||||
getResource(region, getResourceLocation())
|
||||
.ifPresent(resource -> save(json, resource));
|
||||
|
||||
return region;
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the given {@link String content} (e.g. {@literal JSON}) to the specified {@link Resource}.
|
||||
*
|
||||
* @param content {@link String} containing the content to save.
|
||||
* @param resource {@link Resource} to save the {@link String content} to; must not be {@literal null}.
|
||||
* @throws IllegalArgumentException if {@link Resource} is {@literal null}.
|
||||
* @see org.springframework.core.io.Resource
|
||||
*/
|
||||
protected void save(@Nullable String content, @NonNull Resource resource) {
|
||||
|
||||
Assert.notNull(resource, "Resource must not be null");
|
||||
|
||||
if (StringUtils.hasText(content)) {
|
||||
try (Writer writer = newWriter(resource)) {
|
||||
writer.write(content, 0, content.length());
|
||||
writer.flush();
|
||||
}
|
||||
catch (IOException cause) {
|
||||
|
||||
String message = String.format("Failed to save content '%s' to Resource [%s]",
|
||||
formatContentForPreview(content), resource.getDescription());
|
||||
|
||||
throw new DataAccessResourceFailureException(message, cause);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@NonNull Writer newWriter(@NonNull Resource resource) throws IOException {
|
||||
return new BufferedWriter(new FileWriter(resource.getFile(), false));
|
||||
}
|
||||
|
||||
@Nullable String formatContentForPreview(@Nullable String content) {
|
||||
|
||||
if (StringUtils.hasText(content)) {
|
||||
|
||||
int length = Math.min(content.length(), CONTENT_PREVIEW_LENGTH);
|
||||
|
||||
content = content.substring(0, length).concat(length < content.length() ? "..." : "");
|
||||
}
|
||||
|
||||
return content;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@NonNull @Override @SuppressWarnings("unchecked")
|
||||
public Region doImportInto(@NonNull Region region) {
|
||||
|
||||
Assert.notNull(region, "Region must not be null");
|
||||
|
||||
// TODO: handle a JSON array of objects and PdxInstances!!!
|
||||
getResource(region)
|
||||
getResource(region, CLASSPATH_RESOURCE_PREFIX)
|
||||
.filter(Resource::exists)
|
||||
.map(this::getContent)
|
||||
.map(this::toPdxInstance)
|
||||
.map(this::toPdx)
|
||||
.ifPresent(pdxInstance -> region.put(getIdentifier(pdxInstance), pdxInstance));
|
||||
|
||||
return region;
|
||||
}
|
||||
|
||||
private @NonNull byte[] getContent(@NonNull Resource resource) {
|
||||
/**
|
||||
* Gets the content of the given {@link Resource} as an array of {@literal Byte#TYPE bytes}.
|
||||
*
|
||||
* @param resource {@link Resource} from which to load the content; must not be {@literal null}.
|
||||
* @return an array of {@link Byte#TYPE bytes} containing the contents of the given {@link Resource}.
|
||||
* @throws IllegalArgumentException if {@link Resource} is {@literal null}.
|
||||
* @throws DataAccessResourceFailureException if an {@link IOException} occurs while reading from
|
||||
* and loading the contents of the given {@link Resource}.
|
||||
* @see org.springframework.core.io.Resource
|
||||
*/
|
||||
protected @NonNull byte[] getContent(@NonNull Resource resource) {
|
||||
|
||||
Assert.notNull(resource, "Resource must not be null");
|
||||
|
||||
try (InputStream in = resource.getInputStream()){
|
||||
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream(in.available());
|
||||
|
||||
byte[] buffer = new byte[32768];
|
||||
byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
|
||||
|
||||
for (int bytesRead = in.read(buffer); bytesRead != -1; bytesRead = in.read(buffer)) {
|
||||
out.write(buffer, 0, bytesRead);
|
||||
out.flush();
|
||||
}
|
||||
|
||||
out.flush();
|
||||
out.close();
|
||||
|
||||
return out.toByteArray();
|
||||
}
|
||||
catch (IOException cause) {
|
||||
@@ -101,27 +224,139 @@ public class JsonCacheDataImporterExporter extends AbstractCacheDataImporterExpo
|
||||
}
|
||||
}
|
||||
|
||||
private Optional<Resource> getResource(@NonNull Region region) {
|
||||
/**
|
||||
* Determines the {@link Object identifier} for the given {@link PdxInstance}.
|
||||
*
|
||||
* @param pdxInstance {@link PdxInstance} to evaluate; must not be {@literal null}.
|
||||
* @return the {@link Object identifier} for the given {@link PdxInstance}.
|
||||
* @throws IllegalArgumentException if {@link PdxInstance} is {@literal null}.
|
||||
* @throws IllegalStateException if the {@link Object identifier} for the {@link PdxInstance}
|
||||
* cannot be determined.
|
||||
* @see org.apache.geode.pdx.PdxInstance
|
||||
* @see #getIdField(PdxInstance)
|
||||
*/
|
||||
protected @NonNull Object getIdentifier(@NonNull PdxInstance pdxInstance) {
|
||||
|
||||
Assert.notNull(pdxInstance, "PdxInstance must not be null");
|
||||
|
||||
Optional<String> idFieldName = CollectionUtils.nullSafeList(pdxInstance.getFieldNames()).stream()
|
||||
.filter(StringUtils::hasText)
|
||||
.filter(pdxInstance::isIdentityField)
|
||||
.findFirst();
|
||||
|
||||
return idFieldName
|
||||
.map(pdxInstance::getField)
|
||||
.orElseGet(() -> getIdField(pdxInstance));
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches for a PDX {@link String field name} on the {@link PdxInstance} named {@literal id} and returns
|
||||
* its value as the {@link Object identifier} for the {@link PdxInstance}.
|
||||
*
|
||||
* @param pdxInstance {@link PdxInstance} to evaluate; must not be {@literal null}.
|
||||
* @return the value of the {@literal id} {@link String field name} of the {@link PdxInstance} if present.
|
||||
* @throws IllegalStateException if the {@link PdxInstance} does not have an {@literal id}
|
||||
* {@link String field name}.
|
||||
* @see org.apache.geode.pdx.PdxInstance
|
||||
* @see #getIdentifier(PdxInstance)
|
||||
*/
|
||||
protected @NonNull Object getIdField(@NonNull PdxInstance pdxInstance) {
|
||||
|
||||
Assert.notNull(pdxInstance, "PdxInstance must not be null");
|
||||
|
||||
return Optional.of(pdxInstance)
|
||||
.filter(it -> it.hasField(ID_FIELD_NAME))
|
||||
.map(it -> it.getField(ID_FIELD_NAME))
|
||||
.orElseThrow(() -> newIllegalStateException("PdxInstance for type [%1$s] has no %2$s",
|
||||
pdxInstance.getClassName(), pdxInstance.hasField(ID_FIELD_NAME) ? "id" : "declared identity field"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a computed {@literal JSON} {@link Resource} containing {@literal JSON} data that will be loaded into
|
||||
* the given a {@link Region}.
|
||||
*
|
||||
* @param region target {@link Region} used to compute the {@literal JSON} {@link Resource} to load.
|
||||
* @return an {@link Optional} {@literal JSON} {@link Resource} containing {@literal JSON} data
|
||||
* to load into the given {@link Region}.
|
||||
* @see org.springframework.core.io.Resource
|
||||
* @see org.apache.geode.cache.Region
|
||||
* @see java.util.Optional
|
||||
*/
|
||||
protected Optional<Resource> getResource(@NonNull Region region, @Nullable String resourcePrefix) {
|
||||
|
||||
Assert.notNull(region, "Region must not be null");
|
||||
|
||||
String regionName = region.getName().toLowerCase();
|
||||
String resourceName = String.format(RESOURCE_NAME_PATTERN, regionName);
|
||||
String resolvedResourcePrefix = StringUtils.hasText(resourcePrefix)
|
||||
? resourcePrefix
|
||||
: CLASSPATH_RESOURCE_PREFIX;
|
||||
|
||||
return getApplicationContext()
|
||||
.map(it -> it.getResource(String.format("classpath:%s", resourceName)));
|
||||
Resource resource = getApplicationContext()
|
||||
.map(it -> it.getResource(String.format("%1$s%2$s", resolvedResourcePrefix, resourceName)))
|
||||
.orElseGet((() -> new ClassPathResource(resourceName)));
|
||||
|
||||
return Optional.of(resource);
|
||||
}
|
||||
|
||||
protected @NonNull Object getIdentifier(@NonNull PdxInstance pdxInstance) {
|
||||
|
||||
String idField = CollectionUtils.nullSafeList(pdxInstance.getFieldNames()).stream()
|
||||
.filter(pdxInstance::isIdentityField)
|
||||
.findFirst()
|
||||
.orElseThrow(() -> newIllegalStateException("PdxInstance for type [%s] has no declared identify field",
|
||||
pdxInstance.getClassName()));
|
||||
|
||||
return pdxInstance.getField(idField);
|
||||
/**
|
||||
* Returns the {@link String file system path} specifying the location for where to export the {@link Resource}.
|
||||
*
|
||||
* @return the {@link String file system path} specifying the location for where to export the {@link Resource}.
|
||||
*/
|
||||
protected @NonNull String getResourceLocation() {
|
||||
return String.format("%1$s%2$s", FILESYSTEM_RESOURCE_PREFIX, System.getProperty("user.dir"));
|
||||
}
|
||||
|
||||
protected PdxInstance toPdxInstance(byte[] json) {
|
||||
return JSONFormatter.fromJSON(json);
|
||||
/**
|
||||
* Convert {@link Object values} contained in the {@link Region} to {@literal JSON}.
|
||||
*
|
||||
* @param region {@link Region} to process; must not be {@literal null}.
|
||||
* @return a {@literal JSON} {@link String} containing the {@link Object values}
|
||||
* from the given {@link Region}.
|
||||
* @see org.apache.geode.cache.Region
|
||||
* @see #toJson(Object)
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
protected @NonNull String toJson(@NonNull Region region) {
|
||||
|
||||
Assert.notNull(region, "Region must not be null");
|
||||
|
||||
StringBuilder json = new StringBuilder("[");
|
||||
|
||||
boolean addComma = false;
|
||||
|
||||
for (Object value : CollectionUtils.nullSafeCollection(region.values())) {
|
||||
json.append(addComma ? ", " : "");
|
||||
json.append(toJson(value));
|
||||
addComma = true;
|
||||
}
|
||||
|
||||
json.append("]");
|
||||
|
||||
return json.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the given {@link Object} into a {@literal JSON} {@link String}.
|
||||
*
|
||||
* @param source {@link Object} to convert into {@literal JSON}.
|
||||
* @return a {@link String} containing the {@literal JSON} generated from the given {@link Object}.
|
||||
* @see #getObjectToJsonConverter()
|
||||
*/
|
||||
protected @NonNull String toJson(@NonNull Object source) {
|
||||
return getObjectToJsonConverter().convert(source);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the array of {@literal JSON} {@link Byte#TYPE bytes} into a {@link PdxInstance}.
|
||||
*
|
||||
* @param json array of {@link Byte#TYPE} containing {@literal JSON} data.
|
||||
* @return a {@link PdxInstance} converted from the {@literal JSON} {@link Byte#TYPE bytes}.
|
||||
* @see org.apache.geode.pdx.PdxInstance
|
||||
* @see #getJsonToPdxConverter()
|
||||
*/
|
||||
protected @NonNull PdxInstance toPdx(@NonNull byte[] json) {
|
||||
return getJsonToPdxConverter().convert(json);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,742 @@
|
||||
/*
|
||||
* Copyright 2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing
|
||||
* permissions and limitations under the License.
|
||||
*/
|
||||
package org.springframework.geode.data.json;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.ArgumentMatchers.isNull;
|
||||
import static org.mockito.Mockito.doNothing;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.doThrow;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoInteractions;
|
||||
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.StringWriter;
|
||||
import java.io.Writer;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Spy;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import org.apache.geode.cache.Region;
|
||||
import org.apache.geode.pdx.PdxInstance;
|
||||
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.dao.DataAccessResourceFailureException;
|
||||
import org.springframework.geode.data.json.converter.JsonToPdxConverter;
|
||||
import org.springframework.geode.data.json.converter.ObjectToJsonConverter;
|
||||
|
||||
import example.app.crm.model.Customer;
|
||||
import example.app.pos.model.LineItem;
|
||||
|
||||
/**
|
||||
* Unit Tests for {@link JsonCacheDataImporterExporter}.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.junit.Test
|
||||
* @see org.mockito.Mockito
|
||||
* @see org.mockito.junit.MockitoJUnitRunner
|
||||
* @see org.apache.geode.cache.Region
|
||||
* @see org.apache.geode.pdx.PdxInstance
|
||||
* @see org.springframework.core.io.Resource
|
||||
* @see org.springframework.geode.data.json.JsonCacheDataImporterExporter
|
||||
* @since 1.3.0
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class JsonCacheDataImporterExporterUnitTests {
|
||||
|
||||
@Spy
|
||||
private JsonCacheDataImporterExporter importer;
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void doExportFromRegionLogsAndSavesJson() {
|
||||
|
||||
String json = "[{ \"name\": \"Jon Doe\"}]";
|
||||
|
||||
Resource mockResource = mock(Resource.class);
|
||||
|
||||
Region<?, ?> mockRegion = mock(Region.class);
|
||||
|
||||
doReturn("TestRegion").when(mockRegion).getName();
|
||||
|
||||
doReturn(JsonCacheDataImporterExporter.FILESYSTEM_RESOURCE_PREFIX).when(importer).getResourceLocation();
|
||||
doReturn(Optional.of(mockResource)).when(this.importer).getResource(eq(mockRegion),
|
||||
eq(JsonCacheDataImporterExporter.FILESYSTEM_RESOURCE_PREFIX));
|
||||
doNothing().when(this.importer).save(anyString(), any(Resource.class));
|
||||
doReturn(json).when(this.importer).toJson(any());
|
||||
|
||||
assertThat(this.importer.doExportFrom(mockRegion)).isEqualTo(mockRegion);
|
||||
|
||||
verify(this.importer, times(1)).toJson(eq(mockRegion));
|
||||
verify(this.importer, times(1))
|
||||
.getResource(eq(mockRegion), eq(JsonCacheDataImporterExporter.FILESYSTEM_RESOURCE_PREFIX));
|
||||
verify(this.importer, times(1)).save(eq(json), eq(mockResource));
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void doExportFromNullRegion() {
|
||||
|
||||
try {
|
||||
this.importer.doExportFrom(null);
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
|
||||
assertThat(expected).hasMessage("Region must not be null");
|
||||
assertThat(expected).hasNoCause();
|
||||
|
||||
throw expected;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void saveJsonToResource() throws IOException {
|
||||
|
||||
String json = "[{ \"name\": \"Jon Doe\"}, { \"name\": \"Jane Doe\"}]";
|
||||
|
||||
StringWriter writer = new StringWriter(json.length());
|
||||
|
||||
Resource mockResource = mock(Resource.class);
|
||||
|
||||
doReturn(writer).when(this.importer).newWriter(eq(mockResource));
|
||||
|
||||
this.importer.save(json, mockResource);
|
||||
|
||||
assertThat(writer.toString()).isEqualTo(json);
|
||||
|
||||
verify(this.importer, times(1)).newWriter(eq(mockResource));
|
||||
}
|
||||
|
||||
@Test(expected = DataAccessResourceFailureException.class)
|
||||
public void saveThrowsIoException() throws IOException {
|
||||
|
||||
Writer mockWriter = mock(Writer.class);
|
||||
|
||||
String json = "[{ \"name\": \"Jon Doe\"}, { \"name\": \"Jane Doe\"}"
|
||||
+ ", { \"name\": \"Pie Doe\"}, { \"name\": \"Sour Doe\"}]";
|
||||
|
||||
Resource mockResource = mock(Resource.class);
|
||||
|
||||
doReturn("/path/to/resource.json").when(mockResource).getDescription();
|
||||
doReturn(mockWriter).when(this.importer).newWriter(eq(mockResource));
|
||||
doThrow(new IOException("TEST")).when(mockWriter).write(anyString(), anyInt(), anyInt());
|
||||
|
||||
try {
|
||||
this.importer.save(json, mockResource);
|
||||
}
|
||||
catch (DataAccessResourceFailureException expected) {
|
||||
|
||||
assertThat(expected)
|
||||
.hasMessageStartingWith("Failed to save content '%s' to Resource [/path/to/resource.json]",
|
||||
this.importer.formatContentForPreview(json));
|
||||
assertThat(expected).hasCauseInstanceOf(IOException.class);
|
||||
assertThat(expected.getCause()).hasMessage("TEST");
|
||||
assertThat(expected.getCause()).hasNoCause();
|
||||
|
||||
throw expected;
|
||||
}
|
||||
finally {
|
||||
verify(this.importer, times(1)).newWriter(eq(mockResource));
|
||||
verify(mockWriter, times(1)).write(eq(json), eq(0), eq(json.length()));
|
||||
}
|
||||
}
|
||||
@Test
|
||||
public void saveWithNoContent() throws IOException {
|
||||
|
||||
Resource mockResource = mock(Resource.class);
|
||||
|
||||
try {
|
||||
this.importer.save(" ", mockResource);
|
||||
}
|
||||
finally {
|
||||
verify(this.importer, never()).newWriter(any(Resource.class));
|
||||
verifyNoInteractions(mockResource);
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void saveWithNullResource() {
|
||||
|
||||
try {
|
||||
this.importer.save("{}", null);
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
|
||||
assertThat(expected).hasMessage("Resource must not be null");
|
||||
assertThat(expected).hasNoCause();
|
||||
|
||||
throw expected;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void doImportIntoPutsPdxIntoRegionForJson() {
|
||||
|
||||
Resource mockResource = mock(Resource.class);
|
||||
|
||||
Region<Integer, PdxInstance> mockRegion = mock(Region.class);
|
||||
|
||||
PdxInstance mockPdxInstance = mock(PdxInstance.class);
|
||||
|
||||
byte[] json = "{ \"name\": \"Jon Doe\"}".getBytes();
|
||||
|
||||
doReturn(Optional.of(mockResource)).when(this.importer).getResource(eq(mockRegion),
|
||||
eq(JsonCacheDataImporterExporter.CLASSPATH_RESOURCE_PREFIX));
|
||||
doReturn(true).when(mockResource).exists();
|
||||
doReturn(json).when(this.importer).getContent(eq(mockResource));
|
||||
doReturn(mockPdxInstance).when(this.importer).toPdx(eq(json));
|
||||
doReturn(1).when(this.importer).getIdentifier(eq(mockPdxInstance));
|
||||
|
||||
assertThat(this.importer.doImportInto(mockRegion)).isEqualTo(mockRegion);
|
||||
|
||||
verify(this.importer, times(1))
|
||||
.getResource(eq(mockRegion), eq(JsonCacheDataImporterExporter.CLASSPATH_RESOURCE_PREFIX));
|
||||
verify(this.importer, times(1)).getContent(eq(mockResource));
|
||||
verify(this.importer, times(1)).toPdx(eq(json));
|
||||
verify(this.importer, times(1)).getIdentifier(eq(mockPdxInstance));
|
||||
verify(mockResource, times(1)).exists();
|
||||
verify(mockRegion, times(1)).put(eq(1), eq(mockPdxInstance));
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void doImportIntoWithNoResource() {
|
||||
|
||||
Region<?, ?> mockRegion = mock(Region.class);
|
||||
|
||||
doReturn(Optional.empty()).when(this.importer)
|
||||
.getResource(eq(mockRegion), eq(JsonCacheDataImporterExporter.CLASSPATH_RESOURCE_PREFIX));
|
||||
|
||||
assertThat(this.importer.doImportInto(mockRegion)).isEqualTo(mockRegion);
|
||||
|
||||
verify(this.importer, times(1)).doImportInto(eq(mockRegion));
|
||||
verify(this.importer, times(1))
|
||||
.getResource(eq(mockRegion), eq(JsonCacheDataImporterExporter.CLASSPATH_RESOURCE_PREFIX));
|
||||
verifyNoMoreInteractions(this.importer);
|
||||
verifyNoInteractions(mockRegion);
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void doImportIntoWithNonExistingResource() {
|
||||
|
||||
Resource mockResource = mock(Resource.class);
|
||||
|
||||
Region<?, ?> mockRegion = mock(Region.class);
|
||||
|
||||
doReturn(Optional.of(mockResource)).when(this.importer)
|
||||
.getResource(eq(mockRegion), eq(JsonCacheDataImporterExporter.CLASSPATH_RESOURCE_PREFIX));
|
||||
doReturn(false).when(mockResource).exists();
|
||||
|
||||
assertThat(this.importer.doImportInto(mockRegion)).isEqualTo(mockRegion);
|
||||
|
||||
verify(this.importer, times(1)).doImportInto(eq(mockRegion));
|
||||
verify(this.importer, times(1))
|
||||
.getResource(eq(mockRegion), eq(JsonCacheDataImporterExporter.CLASSPATH_RESOURCE_PREFIX));
|
||||
verify(mockResource, times(1)).exists();
|
||||
verifyNoMoreInteractions(this.importer);
|
||||
verifyNoMoreInteractions(mockResource);
|
||||
verifyNoInteractions(mockRegion);
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void doImportIntoWithResourceContainingNoContent() {
|
||||
|
||||
Resource mockResource = mock(Resource.class);
|
||||
|
||||
Region<?, ?> mockRegion = mock(Region.class);
|
||||
|
||||
doReturn(Optional.of(mockResource)).when(this.importer)
|
||||
.getResource(eq(mockRegion), eq(JsonCacheDataImporterExporter.CLASSPATH_RESOURCE_PREFIX));
|
||||
doReturn(true).when(mockResource).exists();
|
||||
doReturn(null).when(this.importer).getContent(eq(mockResource));
|
||||
|
||||
assertThat(this.importer.doImportInto(mockRegion)).isEqualTo(mockRegion);
|
||||
|
||||
verify(this.importer, times(1)).doImportInto(eq(mockRegion));
|
||||
verify(this.importer, times(1))
|
||||
.getResource(eq(mockRegion), eq(JsonCacheDataImporterExporter.CLASSPATH_RESOURCE_PREFIX));
|
||||
verify(this.importer, times(1)).getContent(eq(mockResource));
|
||||
verify(mockResource, times(1)).exists();
|
||||
verifyNoMoreInteractions(this.importer);
|
||||
verifyNoMoreInteractions(mockResource);
|
||||
verifyNoInteractions(mockRegion);
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void doImportIntoWithNoPdxInstance() {
|
||||
|
||||
Resource mockResource = mock(Resource.class);
|
||||
|
||||
Region<?, ?> mockRegion = mock(Region.class);
|
||||
|
||||
byte[] json = "[]".getBytes();
|
||||
|
||||
doReturn(Optional.of(mockResource)).when(this.importer)
|
||||
.getResource(eq(mockRegion), eq(JsonCacheDataImporterExporter.CLASSPATH_RESOURCE_PREFIX));
|
||||
doReturn(true).when(mockResource).exists();
|
||||
doReturn(json).when(this.importer).getContent(eq(mockResource));
|
||||
doReturn(null).when(this.importer).toPdx(eq(json));
|
||||
|
||||
assertThat(this.importer.doImportInto(mockRegion)).isEqualTo(mockRegion);
|
||||
|
||||
verify(this.importer, times(1)).doImportInto(eq(mockRegion));
|
||||
verify(this.importer, times(1))
|
||||
.getResource(eq(mockRegion), eq(JsonCacheDataImporterExporter.CLASSPATH_RESOURCE_PREFIX));
|
||||
verify(this.importer, times(1)).getContent(eq(mockResource));
|
||||
verify(this.importer, times(1)).toPdx(eq(json));
|
||||
verify(mockResource, times(1)).exists();
|
||||
verifyNoMoreInteractions(this.importer);
|
||||
verifyNoMoreInteractions(mockResource);
|
||||
verifyNoInteractions(mockRegion);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void doImportIntoNullRegion() {
|
||||
|
||||
try {
|
||||
this.importer.doImportInto(null);
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
|
||||
assertThat(expected).hasMessage("Region must not be null");
|
||||
assertThat(expected).hasNoCause();
|
||||
|
||||
throw expected;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getContentFromResource() throws IOException {
|
||||
|
||||
byte[] json = "{ \"name\": \"Jon Doe\" }".getBytes();
|
||||
|
||||
ByteArrayInputStream in = spy(new ByteArrayInputStream(json));
|
||||
|
||||
Resource mockResource = mock(Resource.class);
|
||||
|
||||
doReturn(in).when(mockResource).getInputStream();
|
||||
|
||||
assertThat(this.importer.getContent(mockResource)).isEqualTo(json);
|
||||
|
||||
verify(mockResource, times(1)).getInputStream();
|
||||
verify(in, times(1)).close();
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void getContentFromNullResource() {
|
||||
|
||||
try {
|
||||
this.importer.getContent(null);
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
|
||||
assertThat(expected).hasMessage("Resource must not be null");
|
||||
assertThat(expected).hasNoCause();
|
||||
|
||||
throw expected;
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expected = DataAccessResourceFailureException.class)
|
||||
public void getContentThrowsIoException() throws IOException {
|
||||
|
||||
Resource mockResource = mock(Resource.class);
|
||||
|
||||
doReturn("Test Resource").when(mockResource).getDescription();
|
||||
doThrow(new IOException("TEST")).when(mockResource).getInputStream();
|
||||
|
||||
try {
|
||||
this.importer.getContent(mockResource);
|
||||
}
|
||||
catch (DataAccessResourceFailureException expected) {
|
||||
|
||||
assertThat(expected).hasMessageStartingWith("Failed to read from Resource [Test Resource]");
|
||||
assertThat(expected).hasCauseInstanceOf(IOException.class);
|
||||
assertThat(expected.getCause()).hasMessage("TEST");
|
||||
assertThat(expected.getCause()).hasNoCause();
|
||||
|
||||
throw expected;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getIdentifierFromPdxInstance() {
|
||||
|
||||
PdxInstance mockPdxInstance = mock(PdxInstance.class);
|
||||
|
||||
doReturn(Arrays.asList("age", "id", "name")).when(mockPdxInstance).getFieldNames();
|
||||
doReturn(true).when(mockPdxInstance).isIdentityField(eq("id"));
|
||||
doReturn(42).when(mockPdxInstance).getField(eq("id"));
|
||||
|
||||
assertThat(this.importer.getIdentifier(mockPdxInstance)).isEqualTo(42);
|
||||
|
||||
verify(this.importer, never()).getIdField(any(PdxInstance.class));
|
||||
verify(mockPdxInstance, times(1)).getFieldNames();
|
||||
verify(mockPdxInstance, times(1)).isIdentityField(eq("age"));
|
||||
verify(mockPdxInstance, times(1)).isIdentityField(eq("id"));
|
||||
verify(mockPdxInstance, never()).isIdentityField(eq("name"));
|
||||
verify(mockPdxInstance, times(1)).getField(eq("id"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getIdentifierFromPdxInstanceHavingNoFields() {
|
||||
|
||||
PdxInstance mockPdxInstance = mock(PdxInstance.class);
|
||||
|
||||
doReturn(null).when(mockPdxInstance).getFieldNames();
|
||||
doReturn(69).when(this.importer).getIdField(eq(mockPdxInstance));
|
||||
|
||||
assertThat(this.importer.getIdentifier(mockPdxInstance)).isEqualTo(69);
|
||||
|
||||
verify(this.importer, times(1)).getIdField(eq(mockPdxInstance));
|
||||
verify(mockPdxInstance, times(1)).getFieldNames();
|
||||
verify(mockPdxInstance, never()).isIdentityField(anyString());
|
||||
verify(mockPdxInstance, never()).getField(anyString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getIdentifierFromPdxInstanceHavingNoIdentityFields() {
|
||||
|
||||
PdxInstance mockPdxInstance = mock(PdxInstance.class);
|
||||
|
||||
doReturn(Arrays.asList("", "age", null, "name", " ")).when(mockPdxInstance).getFieldNames();
|
||||
doReturn(false).when(mockPdxInstance).isIdentityField(anyString());
|
||||
doReturn(101).when(this.importer).getIdField(eq(mockPdxInstance));
|
||||
|
||||
assertThat(this.importer.getIdentifier(mockPdxInstance)).isEqualTo(101);
|
||||
|
||||
verify(this.importer, times(1)).getIdField(eq(mockPdxInstance));
|
||||
verify(mockPdxInstance, times(1)).getFieldNames();
|
||||
verify(mockPdxInstance, times(1)).isIdentityField(eq("age"));
|
||||
verify(mockPdxInstance, times(1)).isIdentityField(eq("name"));
|
||||
verify(mockPdxInstance, never()).isIdentityField(isNull());
|
||||
verify(mockPdxInstance, never()).isIdentityField(eq(""));
|
||||
verify(mockPdxInstance, never()).isIdentityField(eq(" "));
|
||||
verify(mockPdxInstance, never()).getField(anyString());
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void getIdentifierFromNullPdxInstance() {
|
||||
|
||||
try {
|
||||
this.importer.getIdentifier(null);
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
|
||||
assertThat(expected).hasMessage("PdxInstance must not be null");
|
||||
assertThat(expected).hasNoCause();
|
||||
|
||||
throw expected;
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void getIdentifierFromPdxInstanceWithNoIdentifier() {
|
||||
|
||||
PdxInstance mockPdxInstance = mock(PdxInstance.class);
|
||||
|
||||
doReturn(Collections.singletonList("name")).when(mockPdxInstance).getFieldNames();
|
||||
doReturn(false).when(mockPdxInstance).isIdentityField(anyString());
|
||||
doThrow(new IllegalStateException("TEST")).when(this.importer).getIdField(eq(mockPdxInstance));
|
||||
|
||||
try {
|
||||
this.importer.getIdentifier(mockPdxInstance);
|
||||
}
|
||||
catch (IllegalStateException expected) {
|
||||
|
||||
assertThat(expected).hasMessage("TEST");
|
||||
assertThat(expected).hasNoCause();
|
||||
|
||||
throw expected;
|
||||
}
|
||||
finally {
|
||||
verify(mockPdxInstance, times(1)).getFieldNames();
|
||||
verify(mockPdxInstance, times(1)).isIdentityField(eq("name"));
|
||||
verify(mockPdxInstance, never()).getField(anyString());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getIdFieldFromPdxInstance() {
|
||||
|
||||
PdxInstance mockPdxInstance = mock(PdxInstance.class);
|
||||
|
||||
doReturn(true).when(mockPdxInstance).hasField(eq(JsonCacheDataImporterExporter.ID_FIELD_NAME));
|
||||
doReturn(42).when(mockPdxInstance).getField(eq(JsonCacheDataImporterExporter.ID_FIELD_NAME));
|
||||
|
||||
assertThat(this.importer.getIdField(mockPdxInstance)).isEqualTo(42);
|
||||
|
||||
verify(mockPdxInstance, times(1))
|
||||
.hasField(eq(JsonCacheDataImporterExporter.ID_FIELD_NAME));
|
||||
verify(mockPdxInstance, times(1))
|
||||
.getField(eq(JsonCacheDataImporterExporter.ID_FIELD_NAME));
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void getIdFieldFromNullPdxInstance() {
|
||||
|
||||
try {
|
||||
this.importer.getIdField(null);
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
|
||||
assertThat(expected).hasMessage("PdxInstance must not be null");
|
||||
assertThat(expected).hasNoCause();
|
||||
|
||||
throw expected;
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void getIdFieldFromPdxInstanceWithNoIdField() {
|
||||
|
||||
PdxInstance mockPdxInstance = mock(PdxInstance.class);
|
||||
|
||||
doReturn(LineItem.class.getName()).when(mockPdxInstance).getClassName();
|
||||
doReturn(false).when(mockPdxInstance).hasField(anyString());
|
||||
|
||||
try {
|
||||
this.importer.getIdField(mockPdxInstance);
|
||||
}
|
||||
catch (IllegalStateException expected) {
|
||||
|
||||
assertThat(expected).hasMessage("PdxInstance for type [%s] has no declared identity field",
|
||||
LineItem.class.getName());
|
||||
assertThat(expected).hasNoCause();
|
||||
|
||||
throw expected;
|
||||
}
|
||||
finally {
|
||||
verify(mockPdxInstance, times(1)).getClassName();
|
||||
verify(mockPdxInstance, times(2))
|
||||
.hasField(eq(JsonCacheDataImporterExporter.ID_FIELD_NAME));
|
||||
verify(mockPdxInstance, never()).getField(anyString());
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void getIdFieldFromPdxInstanceWithNoId() {
|
||||
|
||||
PdxInstance mockPdxInstance = mock(PdxInstance.class);
|
||||
|
||||
doReturn(true).when(mockPdxInstance).hasField(anyString());
|
||||
doReturn(null).when(mockPdxInstance).getField(eq(JsonCacheDataImporterExporter.ID_FIELD_NAME));
|
||||
doReturn(LineItem.class.getName()).when(mockPdxInstance).getClassName();
|
||||
|
||||
try {
|
||||
this.importer.getIdField(mockPdxInstance);
|
||||
}
|
||||
catch (IllegalStateException expected) {
|
||||
|
||||
assertThat(expected).hasMessage("PdxInstance for type [%s] has no id",
|
||||
LineItem.class.getName());
|
||||
assertThat(expected).hasNoCause();
|
||||
|
||||
throw expected;
|
||||
}
|
||||
finally {
|
||||
verify(mockPdxInstance, times(1)).getClassName();
|
||||
verify(mockPdxInstance, times(1))
|
||||
.getField(eq(JsonCacheDataImporterExporter.ID_FIELD_NAME));
|
||||
verify(mockPdxInstance, times(2))
|
||||
.hasField(eq(JsonCacheDataImporterExporter.ID_FIELD_NAME));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getResourceFromRegionAndResourcePrefix() {
|
||||
|
||||
ApplicationContext mockApplicationContext = mock(ApplicationContext.class);
|
||||
|
||||
Region<?, ?> mockRegion = mock(Region.class);
|
||||
|
||||
Resource mockResource = mock(Resource.class);
|
||||
|
||||
doReturn(mockResource).when(mockApplicationContext).getResource(anyString());
|
||||
doReturn("Example").when(mockRegion).getName();
|
||||
doReturn(Optional.of(mockApplicationContext)).when(this.importer).getApplicationContext();
|
||||
|
||||
assertThat(this.importer.getResource(mockRegion, "sftp://host/resources/").orElse(null))
|
||||
.isEqualTo(mockResource);
|
||||
|
||||
verify(mockApplicationContext, times(1))
|
||||
.getResource(eq("sftp://host/resources/data-example.json"));
|
||||
verify(mockRegion, times(1)).getName();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getResourceWhenApplicationContextIsNotPresent() {
|
||||
|
||||
Region<?, ?> mockRegion = mock(Region.class);
|
||||
|
||||
doReturn("TEST").when(mockRegion).getName();
|
||||
|
||||
Resource resource = this.importer.getResource(mockRegion, "file://").orElse(null);
|
||||
|
||||
assertThat(resource).isInstanceOf(ClassPathResource.class);
|
||||
assertThat(((ClassPathResource) resource).getPath()).isEqualTo("data-test.json");
|
||||
|
||||
verify(mockRegion, times(1)).getName();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getResourceWhenApplicationContextReturnsNoResource() {
|
||||
|
||||
ApplicationContext mockApplicationContext = mock(ApplicationContext.class);
|
||||
|
||||
Region<?, ?> mockRegion = mock(Region.class);
|
||||
|
||||
doReturn(null).when(mockApplicationContext).getResource(anyString());
|
||||
doReturn("MocK").when(mockRegion).getName();
|
||||
doReturn(Optional.ofNullable(mockApplicationContext)).when(this.importer).getApplicationContext();
|
||||
|
||||
Resource resource = this.importer.getResource(mockRegion, null).orElse(null);
|
||||
|
||||
assertThat(resource).isInstanceOf(ClassPathResource.class);
|
||||
assertThat(((ClassPathResource) resource).getPath()).isEqualTo("data-mock.json");
|
||||
|
||||
verify(mockApplicationContext, times(1))
|
||||
.getResource(eq("classpath:data-mock.json"));
|
||||
verify(mockRegion, times(1)).getName();
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void getResourceFromNullRegion() {
|
||||
|
||||
try {
|
||||
this.importer.getResource(null, JsonCacheDataImporterExporter.CLASSPATH_RESOURCE_PREFIX);
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
|
||||
assertThat(expected).hasMessage("Region must not be null");
|
||||
assertThat(expected).hasNoCause();
|
||||
|
||||
throw expected;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getResourceLocationIsInWorkingDirectory() {
|
||||
assertThat(this.importer.getResourceLocation()).isEqualTo(String.format("%1$s%2$s",
|
||||
JsonCacheDataImporterExporter.FILESYSTEM_RESOURCE_PREFIX, System.getProperty("user.dir")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void toJsonFromRegion() {
|
||||
|
||||
String jonDoeJson = "{ \"name\": \"Jon Doe\" }";
|
||||
String janeDoeJson = "{ \"name\": \"Jane Doe\" }";
|
||||
String pieDoeJson = "{ \"name\": \"Pie Doe\" }";
|
||||
String expectedJson = String.format("[%1$s, %2$s, %3$s]", jonDoeJson, janeDoeJson, pieDoeJson);
|
||||
|
||||
Customer jonDoe = Customer.newCustomer(1L, "Jon Doe");
|
||||
Customer janeDoe = Customer.newCustomer(2L, "Jane Doe");
|
||||
Customer pieDoe = Customer.newCustomer(3L, "Pie Doe");
|
||||
|
||||
Region<?, ?> customers = mock(Region.class);
|
||||
|
||||
doReturn(Arrays.asList(jonDoe, janeDoe, pieDoe)).when(customers).values();
|
||||
doReturn(jonDoeJson).when(this.importer).toJson(eq(jonDoe));
|
||||
doReturn(janeDoeJson).when(this.importer).toJson(eq(janeDoe));
|
||||
doReturn(pieDoeJson).when(this.importer).toJson(eq(pieDoe));
|
||||
|
||||
assertThat(this.importer.toJson(customers)).isEqualTo(expectedJson);
|
||||
|
||||
verify(this.importer, times(1)).toJson(eq(jonDoe));
|
||||
verify(this.importer, times(1)).toJson(eq(janeDoe));
|
||||
verify(this.importer, times(1)).toJson(eq(pieDoe));
|
||||
verify(customers, times(1)).values();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void toJsonFromEmptyRegion() {
|
||||
|
||||
Region<?, ?> mockRegion = mock(Region.class);
|
||||
|
||||
assertThat(this.importer.toJson(mockRegion)).isEqualTo("[]");
|
||||
|
||||
verify(mockRegion, times(1)).values();
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void toJsonFromNullRegion() {
|
||||
|
||||
try {
|
||||
this.importer.toJson(null);
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
|
||||
assertThat(expected).hasMessage("Region must not be null");
|
||||
assertThat(expected).hasNoCause();
|
||||
|
||||
throw expected;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void toJsonFromObjectCallsObjectToJsonConverter() {
|
||||
|
||||
String json = "{ \"name\": \"Jon Doe\" }";
|
||||
|
||||
ObjectToJsonConverter mockConverter = mock(ObjectToJsonConverter.class);
|
||||
|
||||
doReturn(mockConverter).when(this.importer).getObjectToJsonConverter();
|
||||
doReturn(json).when(mockConverter).convert(eq("TEST"));
|
||||
|
||||
assertThat(this.importer.toJson("TEST")).isEqualTo(json);
|
||||
|
||||
verify(this.importer, times(1)).getObjectToJsonConverter();
|
||||
verify(mockConverter, times(1)).convert(eq("TEST"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void toPdxFromJsonCallsJsonToPdxConverter() {
|
||||
|
||||
byte[] json = "{ \"name\": \"Jon Doe\" }".getBytes();
|
||||
|
||||
JsonToPdxConverter mockConverter = mock(JsonToPdxConverter.class);
|
||||
|
||||
PdxInstance mockPdxInstance = mock(PdxInstance.class);
|
||||
|
||||
doReturn(mockConverter).when(this.importer).getJsonToPdxConverter();
|
||||
doReturn(mockPdxInstance).when(mockConverter).convert(eq(json));
|
||||
|
||||
assertThat(this.importer.toPdx(json)).isEqualTo(mockPdxInstance);
|
||||
|
||||
verify(this.importer, times(1)).getJsonToPdxConverter();
|
||||
verify(mockConverter, times(1)).convert(eq(json));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user