1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 package org.apache.dolphinscheduler.common.task; 18 19 import java.lang.reflect.Constructor; 20 import java.lang.reflect.InvocationTargetException; 21 import java.lang.reflect.Method; 22 import java.util.*; 23 24 /** 25 * entity test utils 26 * //该类是一个工具类,可以对传入的任何其他类进行检测,会依次调用类中的所有方法,用了反射机制。 27 */ 28 public class EntityTestUtils { 29 //初始化一个用来存储测试用的类型和对应的数值map数组 30 private static final Map<String, Object> OBJECT_MAP = new HashMap<>(); 31 //遇到这些方法直接跳过,不测试。 32 private static final String SKIP_METHOD = "getClass,notify,notifyAll,wait,equals,hashCode,clone"; 33 String 34 static { 35 //初始化参数数组 36 OBJECT_MAP.put("java.lang.Long", 1L); 37 OBJECT_MAP.put("java.lang.String", "test"); 38 OBJECT_MAP.put("java.lang.Integer", 1); 39 OBJECT_MAP.put("int", 1); 40 OBJECT_MAP.put("long", 1L); 41 OBJECT_MAP.put("java.util.Date", new Date()); 42 OBJECT_MAP.put("char", '1'); 43 OBJECT_MAP.put("java.util.Map", new HashMap()); 44 OBJECT_MAP.put("boolean", true); 45 } 46 //传入要测试的类,可以看到,入参是一个Class类型的数组,代表可以同时测试多个类 47 public static void run(List<Class> classList) 48 throws IllegalAccessException, InvocationTargetException, InstantiationException { 49 //一个个来,先取出第一个要测试的Class,比如是String.class 50 for (Class temp : classList) { 51 Object tempInstance = new Object(); 52 //获取要测试的类中所有的构造方法,不管是有参构造方法还是无参构造方法,比如String.class中的String()构造方法和String(String original) 等等 53 Constructor[] constructors = temp.getConstructors(); 54 //遍历所有的构造方法 55 for (Constructor constructor : constructors) { 56 //获取构造方法的参数类型,如果是无参构造方法,就会进入下面的if,如果是有参构造方法,就会进入下面的else去。 57 final Class<?>[] parameterTypes = constructor.getParameterTypes(); 58 //无参构造方法,会进入这里的if 59 if (parameterTypes.length == 0) { 60 //用反射的机制,直接调用了这个无参构造方法,相当于完成了测试 61 tempInstance = constructor.newInstance(); 62 } else { 63 //objects中存储的是参数的值,如果构造方法需要传入第一个是int,第二个是String,那么这个objects其实就是传入了(1,‘1’)这两个值 64 Object[] objects = new Object[parameterTypes.length]; 65 //这里就是往objects中塞数据 66 for (int i = 0; i < parameterTypes.length; i++) { 67 objects[i] = OBJECT_MAP.get(parameterTypes[i].getName()); 68 } 69 //用反射的机制,直接调用了这个有参数的构造方法,相当于完成了测试 70 tempInstance = constructor.newInstance(objects); 71 } 72 } 73 //这里是对类中的普通方法(除了构造方法外的所有其他方法)做测试 74 Method[] methods = temp.getMethods(); 75 //遍历所有的普通方法 76 for (final Method method : methods) { 77 //如果是需要跳过不进行测试的方法,那么就直接跳过 78 if (SKIP_METHOD.contains(method.getName())) { 79 break; 80 } 81 //同样也是获取到参数的类型 82 final Class<?>[] parameterTypes = method.getParameterTypes(); 83 //如果是有参方法,进入if,无参方法进入else 84 if (parameterTypes.length != 0) { 85 //objects中存储的是参数的值,如果构造方法需要传入第一个是int,第二个是String,那么这个objects其实就是传入了(1,‘1’)这两个值 86 Object[] objects = new Object[parameterTypes.length]; 87 //这里就是往objects中塞数据 88 for (int i = 0; i < parameterTypes.length; i++) { 89 objects[i] = OBJECT_MAP.get(parameterTypes[i].getName()); 90 } 91 //用反射的机制,直接调用了这个有参数的方法,相当于完成了测试 92 method.invoke(tempInstance, objects); 93 } else { 94 //用反射的机制,直接调用了这个无参的方法,相当于完成了测试 95 method.invoke(tempInstance); 96 } 97 } 98 } 99 } 100 }
以下是DolphinScheduler源码中对这个类进行使用的方式,可以参考:
1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 package org.apache.dolphinscheduler.common.task; 18 19 import org.apache.dolphinscheduler.common.task.sqoop.SqoopParameters; 20 import org.apache.dolphinscheduler.common.task.sqoop.sources.SourceHdfsParameter; 21 import org.apache.dolphinscheduler.common.task.sqoop.sources.SourceHiveParameter; 22 import org.apache.dolphinscheduler.common.task.sqoop.sources.SourceMysqlParameter; 23 import org.apache.dolphinscheduler.common.task.sqoop.targets.TargetHdfsParameter; 24 import org.apache.dolphinscheduler.common.task.sqoop.targets.TargetHiveParameter; 25 import org.apache.dolphinscheduler.common.task.sqoop.targets.TargetMysqlParameter; 26 import org.junit.Assert; 27 import org.junit.Test; 28 import java.util.ArrayList; 29 import java.util.List; 30 31 /** 32 * sqoop parameter entity test 33 */ 34 public class SqoopParameterEntityTest { 35 36 @Test 37 public void testEntity(){ 38 try { 39 List<Class> classList = new ArrayList<>(); 40 classList.add(SourceMysqlParameter.class); 41 classList.add(SourceHiveParameter.class); 42 classList.add(SourceHdfsParameter.class); 43 classList.add(SqoopParameters.class); 44 classList.add(TargetMysqlParameter.class); 45 classList.add(TargetHiveParameter.class); 46 classList.add(TargetHdfsParameter.class); 47 EntityTestUtils.run(classList); 48 } catch (Exception e) { 49 Assert.fail(e.getMessage()); 50 } 51 } 52 }