756d17534c58d7974e2ece29cac32e6016bd4f1e
[vid.git] / vid-app-common / src / test / java / org / onap / vid / testUtils / TestUtils.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * VID
4  * ================================================================================
5  * Copyright (C) 2017 - 2019 AT&T Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  * 
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  * 
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  * ============LICENSE_END=========================================================
19  */
20
21 package org.onap.vid.testUtils;
22
23 import static java.util.function.Function.identity;
24 import static java.util.stream.Collectors.toList;
25 import static java.util.stream.Collectors.toMap;
26 import static org.apache.commons.beanutils.PropertyUtils.getPropertyDescriptors;
27 import static org.mockito.Matchers.any;
28 import static org.mockito.Mockito.RETURNS_DEFAULTS;
29 import static org.mockito.Mockito.mock;
30 import static org.mockito.Mockito.when;
31 import static org.mockito.Mockito.withSettings;
32 import static org.testng.Assert.fail;
33
34 import com.fasterxml.jackson.databind.DeserializationFeature;
35 import com.fasterxml.jackson.databind.ObjectMapper;
36 import com.google.common.collect.ImmutableList;
37 import java.beans.PropertyDescriptor;
38 import java.io.ByteArrayInputStream;
39 import java.io.IOException;
40 import java.io.InputStream;
41 import java.io.Serializable;
42 import java.net.URI;
43 import java.util.Arrays;
44 import java.util.Iterator;
45 import java.util.List;
46 import javax.ws.rs.client.Client;
47 import javax.ws.rs.client.Invocation;
48 import javax.ws.rs.client.WebTarget;
49 import javax.ws.rs.core.GenericType;
50 import javax.ws.rs.core.MediaType;
51 import javax.ws.rs.core.Response;
52 import org.apache.commons.beanutils.BeanUtils;
53 import org.apache.commons.lang3.reflect.MethodUtils;
54 import org.apache.log4j.LogManager;
55 import org.apache.log4j.Logger;
56 import org.json.JSONArray;
57 import org.json.JSONObject;
58 import org.junit.Assert;
59 import org.mockito.MockSettings;
60 import org.mockito.Mockito;
61 import org.mockito.invocation.InvocationOnMock;
62 import org.mockito.stubbing.Answer;
63 import org.onap.portalsdk.core.util.SystemProperties;
64 import org.onap.vid.asdc.beans.Service;
65 import org.springframework.core.env.Environment;
66 import org.springframework.mock.env.MockEnvironment;
67
68 /**
69  * Created by Oren on 6/7/17.
70  */
71 public class TestUtils {
72
73     private static final Logger logger = LogManager.getLogger(TestUtils.class);
74
75     /**
76      * The method compares between two jsons. the function assert that the actual object does not reduce or change the functionallity/parsing of the expected json.
77      * This means that if the expected JSON has a key which is null or the JSON doesn't have a key which contained in the expected JSON the assert will succeed and the will pass.
78      * For example : For JSON expected = {a:null} and actual {a:3} the test will pass
79      * Other example : For JSON expected = {a:3} and actual {a:null} the test will fail
80      *
81      * @param expected JSON
82      * @param actual JSON
83      */
84     public static void assertJsonStringEqualsIgnoreNulls(String expected, String actual) {
85         if (expected == null || expected == JSONObject.NULL) {return;}
86
87         JSONObject expectedJSON = new JSONObject(expected);
88         JSONObject actualJSON = new JSONObject(actual);
89         Iterator<?> keys = expectedJSON.keys();
90
91         while( keys.hasNext() ) {
92             String key = (String)keys.next();
93             Object expectedValue = expectedJSON.get(key);
94             if (expectedValue == JSONObject.NULL){
95                 continue;
96             }
97
98             Object actualValue = actualJSON.get(key);
99
100             if (expectedValue instanceof JSONObject) {
101                 String expectedVal = expectedValue.toString();
102                 String actualVal = actualValue.toString();
103                 assertJsonStringEqualsIgnoreNulls(expectedVal, actualVal);
104             }
105             else if (expectedValue instanceof JSONArray) {
106                 if (actualValue instanceof JSONArray) {
107                     JSONArray expectedJSONArray = (JSONArray)expectedValue;
108                     JSONArray actualJSONArray = (JSONArray)actualValue;
109                     for (int i = 0; i < expectedJSONArray.length(); i++) {
110                         String expectedItem = expectedJSONArray.get(i).toString();
111                         String actualItem = actualJSONArray.get(i).toString();
112                         if (expectedValue instanceof JSONObject)
113                             assertJsonStringEqualsIgnoreNulls(expectedItem, actualItem);
114                     }
115                 }
116                 else {
117                     fail("expected: " + expectedValue + " got:" + actualValue);
118                 }
119             }
120             else {
121                 Assert.assertEquals("assertion fail for key:"+key, expectedValue, actualValue);
122             }
123         }
124     }
125
126     public static <T> T readJsonResourceFileAsObject(String pathInResource, Class<T> valueType) throws IOException {
127         return readJsonResourceFileAsObject(pathInResource, valueType, false);
128     }
129
130     public static <T> T readJsonResourceFileAsObject(String pathInResource, Class<T> valueType, boolean ignoreUnknownProperties)
131             throws IOException {
132         ObjectMapper objectMapper = new ObjectMapper();
133         objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, ignoreUnknownProperties);
134         return objectMapper.readValue(
135                 TestUtils.class.getResource(pathInResource),
136                 valueType);
137     }
138
139     public static String[] allPropertiesOf(Class<?> aClass) {
140         return Arrays.stream(getPropertyDescriptors(aClass))
141             .map(PropertyDescriptor::getDisplayName)
142             .toArray(String[]::new);
143     }
144
145     private static <T> List<String> allStringPropertiesOf(T object) {
146         return Arrays.stream(getPropertyDescriptors(object.getClass()))
147             .filter(descriptor -> descriptor.getPropertyType().isAssignableFrom(String.class))
148             .map(PropertyDescriptor::getDisplayName)
149             .collect(toList());
150     }
151
152     /**
153      * Sets each String property with a value equal to the name of
154      * the property; e.g.: { name: "name", city: "city" }
155      * @param object
156      * @param <T>
157      * @return The modified object
158      */
159     public static <T> T setStringsInStringProperties(T object) {
160         try {
161             final List<String> stringFields = allStringPropertiesOf(object);
162
163             BeanUtils.populate(object, stringFields.stream()
164                 .collect(toMap(identity(), identity())));
165
166             return object;
167         } catch (Exception e) {
168             throw new RuntimeException(e);
169         }
170     }
171
172
173     public static class JavaxRsClientMocks {
174         private final javax.ws.rs.client.Client fakeClient;
175         private final javax.ws.rs.client.Invocation.Builder fakeBuilder;
176         private final javax.ws.rs.client.Invocation fakeInvocation;
177         private final Response fakeResponse;
178
179         public javax.ws.rs.client.Client getFakeClient() {
180             return fakeClient;
181         }
182
183         public javax.ws.rs.client.Invocation.Builder getFakeBuilder() {
184             return fakeBuilder;
185         }
186
187         public Response getFakeResponse() {
188             return fakeResponse;
189         }
190
191         public JavaxRsClientMocks() {
192             final MockSettings mockSettings = withSettings().defaultAnswer(new TriesToReturnMockByType());
193
194             fakeClient = mock(javax.ws.rs.client.Client.class, mockSettings);
195             fakeBuilder = mock(javax.ws.rs.client.Invocation.Builder.class, mockSettings);
196             fakeInvocation = mock(javax.ws.rs.client.Invocation.class, mockSettings);
197             fakeResponse = mock(Response.class, mockSettings);
198             final javax.ws.rs.client.WebTarget fakeWebTarget = mock(javax.ws.rs.client.WebTarget.class, mockSettings);
199
200             TriesToReturnMockByType.setAvailableMocks(
201                     fakeClient,
202                     fakeWebTarget,
203                     fakeBuilder,
204                     fakeInvocation,
205                     fakeResponse
206             );
207             Mockito.when(fakeBuilder.get(any(Class.class))).thenReturn(null);
208             Mockito.when(fakeBuilder.get(any(GenericType.class))).thenReturn(null);
209             Mockito.when(fakeResponse.getStatus()).thenReturn(200);
210             Mockito.when(fakeResponse.getStatusInfo()).thenReturn(Response.Status.OK);
211             Mockito.when(fakeResponse.readEntity(Service.class)).thenReturn(null);
212             Mockito.when(fakeResponse.readEntity(InputStream.class)).thenReturn(new ByteArrayInputStream(new byte[]{}));
213             Mockito.when(fakeResponse.readEntity(String.class)).thenReturn(null);
214         }
215     }
216
217     /*
218        inspired out from newer Mockito version
219         returns a mock from given list if it's a matching return-type
220     */
221     private static class TriesToReturnMockByType implements Answer<Object>, Serializable {
222         private final Answer<Object> defaultReturn = RETURNS_DEFAULTS;
223         private static List<Object> availableMocks = ImmutableList.of();
224
225         static void setAvailableMocks(Object... mocks) {
226             availableMocks = ImmutableList.copyOf(mocks);
227         }
228
229         public Object answer(InvocationOnMock invocation) throws Throwable {
230             Class<?> methodReturnType = invocation.getMethod().getReturnType();
231
232             return availableMocks.stream()
233                     .filter(mock -> methodReturnType.isAssignableFrom(mock.getClass()))
234                     //.peek(m -> logger.info("found a mock: " + m.getClass().getName()))
235                     .findFirst()
236                     .orElse(defaultReturn.answer(invocation));
237         }
238     }
239
240
241     //The method mocks only some methods used in my case
242     //You may add some other when for your test here
243     public static Response mockResponseForJavaxClient(Client javaxClientMock) {
244         Response  mockResponse = mock(Response.class);
245         WebTarget webTarget = mock(WebTarget.class);
246         Invocation.Builder builder = mock(Invocation.Builder.class);
247         when(javaxClientMock.target(any(URI.class))).thenReturn(webTarget);
248         when(webTarget.path(any())).thenReturn(webTarget);
249         when(webTarget.request(any(MediaType.class))).thenReturn(builder);
250         when(builder.headers(any())).thenReturn(builder);
251         when(builder.header(any(), any())).thenReturn(builder);
252         when(builder.get()).thenReturn(mockResponse);
253         return mockResponse;
254     }
255
256
257     public interface Test {
258
259         void apply();
260     }
261
262     public static void testWithSystemProperty(String key, String value, Test test) throws Exception {
263         SystemProperties systemProperties = new SystemProperties();
264         //use reflection to invoke protected method
265         Environment originalEnvironment = (Environment) MethodUtils
266             .invokeMethod(systemProperties, true, "getEnvironment");
267
268         try {
269             Environment environment = mock(Environment.class);
270             systemProperties.setEnvironment(environment);
271             when(environment.getRequiredProperty(key)).thenReturn(value);
272             when(environment.containsProperty(key)).thenReturn(true);
273             test.apply();
274         }
275         finally {
276             systemProperties.setEnvironment(originalEnvironment);
277         }
278     }
279
280 }