001/*
002 * Copyright 2012-2017 the original author or authors.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *      http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017package org.springframework.boot.test.json;
018
019import java.io.IOException;
020import java.io.Reader;
021
022import com.google.gson.Gson;
023
024import org.springframework.beans.factory.ObjectFactory;
025import org.springframework.core.ResolvableType;
026import org.springframework.util.Assert;
027
028/**
029 * AssertJ based JSON tester backed by Gson. Usually instantiated via
030 * {@link #initFields(Object, Gson)}, for example: <pre class="code">
031 * public class ExampleObjectJsonTests {
032 *
033 *     private GsonTester&lt;ExampleObject&gt; json;
034 *
035 *     &#064;Before
036 *     public void setup() {
037 *         Gson gson = new GsonBuilder().create();
038 *         GsonTester.initFields(this, gson);
039 *     }
040 *
041 *     &#064;Test
042 *     public void testWriteJson() throws IOException {
043 *         ExampleObject object = //...
044 *         assertThat(json.write(object)).isEqualToJson("expected.json");
045 *     }
046 *
047 * }
048 * </pre>
049 *
050 * See {@link AbstractJsonMarshalTester} for more details.
051 *
052 * @param <T> the type under test
053 * @author Phillip Webb
054 * @since 1.4.0
055 */
056public class GsonTester<T> extends AbstractJsonMarshalTester<T> {
057
058        private final Gson gson;
059
060        /**
061         * Create a new uninitialized {@link GsonTester} instance.
062         * @param gson the Gson instance
063         */
064        protected GsonTester(Gson gson) {
065                Assert.notNull(gson, "Gson must not be null");
066                this.gson = gson;
067        }
068
069        /**
070         * Create a new {@link GsonTester} instance.
071         * @param resourceLoadClass the source class used to load resources
072         * @param type the type under test
073         * @param gson the Gson instance
074         * @see #initFields(Object, Gson)
075         */
076        public GsonTester(Class<?> resourceLoadClass, ResolvableType type, Gson gson) {
077                super(resourceLoadClass, type);
078                Assert.notNull(gson, "Gson must not be null");
079                this.gson = gson;
080        }
081
082        @Override
083        protected String writeObject(T value, ResolvableType type) throws IOException {
084                return this.gson.toJson(value, type.getType());
085        }
086
087        @Override
088        protected T readObject(Reader reader, ResolvableType type) throws IOException {
089                return this.gson.fromJson(reader, type.getType());
090        }
091
092        /**
093         * Utility method to initialize {@link GsonTester} fields. See {@link GsonTester
094         * class-level documentation} for example usage.
095         * @param testInstance the test instance
096         * @param gson the Gson instance
097         */
098        public static void initFields(Object testInstance, Gson gson) {
099                new GsonFieldInitializer().initFields(testInstance, gson);
100        }
101
102        /**
103         * Utility method to initialize {@link GsonTester} fields. See {@link GsonTester
104         * class-level documentation} for example usage.
105         * @param testInstance the test instance
106         * @param gson an object factory to create the Gson instance
107         */
108        public static void initFields(Object testInstance, ObjectFactory<Gson> gson) {
109                new GsonFieldInitializer().initFields(testInstance, gson);
110        }
111
112        /**
113         * {@link FieldInitializer} for Gson.
114         */
115        private static class GsonFieldInitializer extends FieldInitializer<Gson> {
116
117                protected GsonFieldInitializer() {
118                        super(GsonTester.class);
119                }
120
121                @Override
122                protected AbstractJsonMarshalTester<Object> createTester(
123                                Class<?> resourceLoadClass, ResolvableType type, Gson marshaller) {
124                        return new GsonTester<>(resourceLoadClass, type, marshaller);
125                }
126
127        }
128
129}