国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

項目工具:兩行代碼快速生成測試的數據的FakeDataMaker

X_AirDu / 2890人閱讀

摘要:開發(fā)原因是一個非常小的類庫,通過代碼生成來提供高性能的反射處理,自動為字段提供訪問類,訪問類使用字節(jié)碼操作而不是的反射技術,因此非常快。

開發(fā)原因

ReflectASM 是一個非常小的 Java 類庫,通過代碼生成來提供高性能的反射處理,自動為 get/set 字段提供訪問類,訪問類使用字節(jié)碼操作而不是 Java 的反射技術,因此非常快。

在單元測試的時,需要模擬制造一些數據去測試我們代碼會不會出現明顯的異常(字段導致、空指針),除了自己亂編寫一些測試數據以外,也會實用javafaker進行“真實數據”模擬,當然可以減少我們的代碼量。如果,只是前期的簡單測試,對數據的正確性并不高,使用javafaker對每個字段都進行編造,代碼量還是不少,于是,這個時候,FakeDataMaker就這么誕生了,一個基于javafaker和ReflectASM工具“亂”填充數據的測試工具

UML圖

源碼分析

AbstractFakeDataMaker

這個類是整個工具的一個基類,定義了各種類型的參數的抽象方法,基本上包括常用的基類,又加上了Date、Boolean、BigDecimal類型

三種類型,這里入參為String fieldName,雖然工具可以亂生成數據,但是,要是有些字段還是需要特殊化的處理,便可以重寫這些方法,根據傳入的字段名稱,進行數據自定義填充,比如

FakeDataMaker onlyFieldOne = new FakeDataMaker(){        @Override        protected String makeString(String fieldName) {            if("data3".equals(fieldName)){                return "zjjdjd";            }            return super.makeString(fieldName);        }    };

這樣便可以自定義data3字段,固定為“zjjdjd”

FakeDataMaker

這是這個工具中最重要的類,繼承了AbstractFakeDataMaker方法,并實現了幾個造數據的方法,目前這個類可以實現兩個功能,一個是填充數據,一個是構造空值的對象

填充數據

調用makeData方法便可以得到一個填充完數據的對象,有兩個makeData方法,默認自定義faker的字符集為中文,也支持自定義字符集

public final Object makeData(Class testClass) {    return makeData(testClass, Locale.CHINA);}

makeData方法中使用了很多緩存,便于遍歷生成數據的速度

//構建對象ConstructorAccess constructorAccess = CONSTRUCTOR_ACCESS_MAP.get(testClass);if (constructorAccess == null) {    constructorAccess = ConstructorAccess.get(testClass);    CONSTRUCTOR_ACCESS_MAP.put(testClass, constructorAccess);}·····//類方法的緩存MethodAccess testAccess = METHOD_ACCESS_MAP.get(testClass);        if (testAccess == null) {            testAccess = MethodAccess.get(testClass);            METHOD_ACCESS_MAP.put(testClass, testAccess);        }····· //字段的緩存 List<Field> fields = FIELDS_MAP.get(testClass);        if (fields == null) {            fields = getAllFields(testClass);            FIELDS_MAP.put(testClass, fields);        }·····  //獲取到對應的get方法的下標緩存 Integer set_index = INDEX_MAP.get(get_key);            if (set_index == null) {                set_index = testAccess.getIndex(GET_METHOD + StringUtils.capitalize(field.getName()));                INDEX_MAP.put(get_key, set_index);}

這里使用了ReflectASM工具的ConstructorAccess、MethodAccess,方便構建對象和獲取到方法的句柄,從而進行賦值,這里為什么會引入ReflectASM工具,因為,我在工作開發(fā)中涉及到一個字段映射的功能實現,使用ReflectASM+注解的方法可以減少大量代碼,所以在測試過程中,乘熱打鐵就ReflectASM工具,不過,主要還是ReflectASM工具真的比較好用

由于我同事第一次使用FakeDataMaker工具就直接使用了基類進行了賦值,然后就報錯了,所以對于傳入基類的賦值做了點特殊處理

//基礎類型的參數構建        if (baseClass(testClass)) {            if (WARNING_FLAG) {                System.err.println("建議直接使用Java—faker生成基礎類數據");                WARNING_FLAG = false;            }            return baseClassValue(testClass, new Object());        }

雖然,不建議對基類進行賦值,使用Java faker會比較更方便,為了避免異常,對主要的幾種基類數據填充

FakeDataMaker util = new FakeDataMaker();Integer testData = (Integer) util.makeData(Integer.class);System.out.println(testData);建議直接使用Java—faker生成基礎類數據87

baseClassValue方法還是調用了內部的賦值方法

如果傳入的類,存在內部類,這里需要setInnerFlag調用方法開啟對內部類的支持

if (INNER_FLAG) {    Boolean baseValue = BASE_MAP.get(get_key);    if (baseValue == null) {        baseValue = !baseClass(field.getType()) && !field.getType().equals(testClass)                && Modifier.toString(field.getType().getModifiers()).contains("static");        BASE_MAP.put(get_key, baseValue);    }    if (baseValue) {        Object baseClassValue = makeData(field.getType(), locale);        testAccess.invoke(testObject, set_index, baseClassValue);    }}

內部類的數據填充,其實是一個遞歸調用makeData

接下來是核心部分,根據字段的數據類型,進行賦值操作,這里就使用到了重寫的AbstractFakeDataMaker**定義的幾個造值方法

if (field.getType() == String.class) {    testAccess.invoke(testObject, set_index, makeString(field.getName()));}if (field.getType() == Integer.class || field.getType() == int.class) {    testAccess.invoke(testObject, set_index, makeInteger(field.getName()));}if (field.getType() == Float.class || field.getType() == float.class) {    testAccess.invoke(testObject, set_index, makeFloat(field.getName()));}if (field.getType() == Double.class || field.getType() == double.class) {    testAccess.invoke(testObject, set_index, makeDouble(field.getName()));}if (field.getType() == Long.class || field.getType() == long.class) {    testAccess.invoke(testObject, set_index, makeLong(field.getName()));}if (field.getType() == Date.class) {    testAccess.invoke(testObject, set_index, makeDate(field.getName()));}if (field.getType() == Boolean.class || field.getType() == boolean.class) {    testAccess.invoke(testObject, set_index, makeBoolean(field.getName()));}if (field.getType() == BigDecimal.class) {    testAccess.invoke(testObject, set_index, makeBigDecimal(field.getName()));}

目前,字符型,填充的是,faker的name類型的字段

@Overrideprotected String makeString(String fieldName) {    return faker.name().fullName();}@Overrideprotected Integer makeInteger(String fieldName) {    return faker.number().numberBetween(1, 100);}@Overrideprotected Float makeFloat(String fieldName) {    Double randomDouble = faker.number().randomDouble(2, 1, 100);    return randomDouble.floatValue();}@Overrideprotected Double makeDouble(String fieldName) {    return faker.number().randomDouble(2, 1, 100);}@Overrideprotected Long makeLong(String fieldName) {    Double randomDouble = faker.number().randomDouble(2, 1, 100);    return randomDouble.longValue();}@Overrideprotected Date makeDate(String fieldName) {    return faker.date().birthday();}@Overrideprotected Boolean makeBoolean(String fieldName) {    if (faker.number().numberBetween(0, 2) == 1) {        return Boolean.TRUE;    }    return Boolean.FALSE;}@Overrideprotected BigDecimal makeBigDecimal(String fieldName) {    Double randomDouble = faker.number().randomDouble(2, 1, 1000);    return new BigDecimal(String.valueOf(randomDouble));}

由于只是簡單的功能測試的數據填充,在數據的準確性上默認方法還是有很大的偏差的,所以,我在實際的使用過程中,大部分還是重寫了造值的各種方法,比如ID字段,就返回uuid,字符的時間、數字等

FakeDataMaker stringOnlyOne = new FakeDataMaker() {    @Override    protected String makeString(String fieldName) {       if ("id".equals(fieldName)) {                    return "1231231231231321";                }      return super.makeString(fieldName);    }};

構造空值

這也是在我同事的代碼中遇到的一個問題,從而想到的一個積極方案,比如一個統計類的VO,會有很多統計的數值屬性,能查到結果的就會賦值,沒有結果的就默認0,如果使用賦值方法則需要把全部的屬性都要賦值默認值0,或者調用構造方法賦值,兩種方法都會有大量的代碼,不太簡潔,尤其使用構造方法,會有很多的入參,使用FakeDataMaker一句代碼就可以完成空值對象的賦值

TestData testData1 = (TestData)  FakeDataMaker.initEmptyObject(TestData.class);

實際效果可以看到,字符類型默認為“”,數字值則是0或者0.0,時間則默認為當前時間
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-F6DTyUik-1633882390009)(https://www.kura.ren/upload/2021/10/%E6%88%AA%E5%B1%8F2021-10-11%20%E4%B8%8A%E5%8D%8812.00.38-0dbbc7a502de44dba717a274079694e4.png)]

空值構建默認只支持對內部類進行值填充的,可以調用 initEmptyObject(Class testClass, Boolean innerFlag) 關閉對內部類的填充

initEmptyObject方法內部是重寫了FakeDataMaker方法,重寫造值方法,為空值,FakeDataMaker內部也緩存了一個FakeDataMaker對象,便于重復的調用

if (EMPTY_OBJECT_MAKER == null || !EMPTY_OBJECT_MAKER.INNER_FLAG.equals(innerFlag)) {    EMPTY_OBJECT_MAKER = new FakeDataMaker() {        @Override        protected String makeString(String fieldName) {            return "";        }        @Override        protected Integer makeInteger(String fieldName) {            return 0;        }        @Override        protected Float makeFloat(String fieldName) {            return 0F;        }        @Override        protected Double makeDouble(String fieldName) {            return 0D;        }        @Override        protected Long makeLong(String fieldName) {            return 0L;        }        @Override        protected Date makeDate(String fieldName) {            //這里沒設置緩存            return new Date();        }        @Override        protected Boolean makeBoolean(String fieldName) {            return Boolean.TRUE;        }        @Override        protected BigDecimal makeBigDecimal(String fieldName) {            return BigDecimal.ZERO;        }    };    EMPTY_OBJECT_MAKER.setInnerFlag(innerFlag);}return EMPTY_OBJECT_MAKER.makeData(testClass);

源碼地址

https://github.com/liuhao192/FakerTestDataMakeUtil

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規(guī)行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/122269.html

相關文章

  • Node.js運行原理、高并發(fā)性能測試對比及生態(tài)圈匯總

    摘要:模式,單實例多進程,常用于多語言混編,比如等,不支持端口復用,需要自己做應用的端口分配和負載均衡的子進程業(yè)務代碼。就是我們需要一個調度者,保證所有后端服務器都將性能充分發(fā)揮,從而保持服務器集群的整體性能最優(yōu),這就是負載均衡。 showImg(https://segmentfault.com/img/remote/1460000019425391?w=1440&h=1080); Nod...

    kamushin233 評論0 收藏0
  • Node.js運行原理、高并發(fā)性能測試對比及生態(tài)圈匯總

    摘要:模式,單實例多進程,常用于多語言混編,比如等,不支持端口復用,需要自己做應用的端口分配和負載均衡的子進程業(yè)務代碼。就是我們需要一個調度者,保證所有后端服務器都將性能充分發(fā)揮,從而保持服務器集群的整體性能最優(yōu),這就是負載均衡。 showImg(https://segmentfault.com/img/remote/1460000019425391?w=1440&h=1080); Nod...

    BDEEFE 評論0 收藏0
  • Node.js運行原理、高并發(fā)性能測試對比及生態(tài)圈匯總

    摘要:模式,單實例多進程,常用于多語言混編,比如等,不支持端口復用,需要自己做應用的端口分配和負載均衡的子進程業(yè)務代碼。就是我們需要一個調度者,保證所有后端服務器都將性能充分發(fā)揮,從而保持服務器集群的整體性能最優(yōu),這就是負載均衡。 showImg(https://segmentfault.com/img/remote/1460000019425391?w=1440&h=1080); Nod...

    TesterHome 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<