001/*
002 * Copyright 2012-2016 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.File;
020import java.io.InputStream;
021import java.nio.charset.Charset;
022
023import org.springframework.core.ResolvableType;
024import org.springframework.core.io.Resource;
025import org.springframework.util.Assert;
026
027/**
028 * AssertJ based JSON tester that works with basic JSON strings. Allows testing of JSON
029 * payloads created from any source, for example:<pre class="code">
030 * public class ExampleObjectJsonTests {
031 *
032 *     private BasicJsonTester json = new BasicJsonTester(getClass());
033 *
034 *     &#064;Test
035 *     public void testWriteJson() throws IOException {
036 *         assertThat(json.from("example.json")).extractingJsonPathStringValue("@.name")
037                                .isEqualTo("Spring");
038 *     }
039 *
040 * }
041 * </pre>
042 *
043 * See {@link AbstractJsonMarshalTester} for more details.
044 *
045 * @author Phillip Webb
046 * @author Andy Wilkinson
047 * @since 1.4.0
048 */
049public class BasicJsonTester {
050
051        private JsonLoader loader;
052
053        /**
054         * Create a new uninitialized {@link BasicJsonTester} instance.
055         */
056        protected BasicJsonTester() {
057        }
058
059        /**
060         * Create a new {@link BasicJsonTester} instance that will load resources as UTF-8.
061         * @param resourceLoadClass the source class used to load resources
062         */
063        public BasicJsonTester(Class<?> resourceLoadClass) {
064                this(resourceLoadClass, null);
065        }
066
067        /**
068         * Create a new {@link BasicJsonTester} instance.
069         * @param resourceLoadClass the source class used to load resources
070         * @param charset the charset used to load resources
071         * @since 1.4.1
072         */
073        public BasicJsonTester(Class<?> resourceLoadClass, Charset charset) {
074                Assert.notNull(resourceLoadClass, "ResourceLoadClass must not be null");
075                this.loader = new JsonLoader(resourceLoadClass, charset);
076        }
077
078        /**
079         * Initialize the marshal tester for use, configuring it to load JSON resources as
080         * UTF-8.
081         * @param resourceLoadClass the source class used when loading relative classpath
082         * resources
083         * @param type the type under test
084         */
085        protected final void initialize(Class<?> resourceLoadClass, ResolvableType type) {
086                this.initialize(resourceLoadClass, null, type);
087        }
088
089        /**
090         * Initialize the marshal tester for use.
091         * @param resourceLoadClass the source class used when loading relative classpath
092         * resources
093         * @param charset the charset used when loading relative classpath resources
094         * @param type the type under test
095         * @since 1.4.1
096         */
097        protected final void initialize(Class<?> resourceLoadClass, Charset charset,
098                        ResolvableType type) {
099                if (this.loader == null) {
100                        this.loader = new JsonLoader(resourceLoadClass, charset);
101                }
102        }
103
104        /**
105         * Create JSON content from the specified String source. The source can contain the
106         * JSON itself or, if it ends with {@code .json}, the name of a resource to be loaded
107         * using {@code resourceLoadClass}.
108         * @param source JSON content or a {@code .json} resource name
109         * @return the JSON content
110         */
111        public JsonContent<Object> from(CharSequence source) {
112                verify();
113                return getJsonContent(this.loader.getJson(source));
114        }
115
116        /**
117         * Create JSON content from the specified resource path.
118         * @param path the path of the resource to load
119         * @param resourceLoadClass the source class used to load the resource
120         * @return the JSON content
121         */
122        public JsonContent<Object> from(String path, Class<?> resourceLoadClass) {
123                verify();
124                return getJsonContent(this.loader.getJson(path, resourceLoadClass));
125        }
126
127        /**
128         * Create JSON content from the specified JSON bytes.
129         * @param source the bytes of JSON
130         * @return the JSON content
131         */
132        public JsonContent<Object> from(byte[] source) {
133                verify();
134                return getJsonContent(this.loader.getJson(source));
135        }
136
137        /**
138         * Create JSON content from the specified JSON file.
139         * @param source the file containing JSON
140         * @return the JSON content
141         */
142        public JsonContent<Object> from(File source) {
143                verify();
144                return getJsonContent(this.loader.getJson(source));
145        }
146
147        /**
148         * Create JSON content from the specified JSON input stream.
149         * @param source the input stream containing JSON
150         * @return the JSON content
151         */
152        public JsonContent<Object> from(InputStream source) {
153                verify();
154                return getJsonContent(this.loader.getJson(source));
155        }
156
157        /**
158         * Create JSON content from the specified JSON resource.
159         * @param source the resource containing JSON
160         * @return the JSON content
161         */
162        public JsonContent<Object> from(Resource source) {
163                verify();
164                return getJsonContent(this.loader.getJson(source));
165        }
166
167        private void verify() {
168                Assert.state(this.loader != null, "Uninitialized BasicJsonTester");
169        }
170
171        private JsonContent<Object> getJsonContent(String json) {
172                return new JsonContent<Object>(this.loader.getResourceLoadClass(), null, json);
173        }
174
175}