成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專欄INFORMATION COLUMN

Junit源碼閱讀(三)之精致的Validator

李世贊 / 3616人閱讀

摘要:前言在建立的過(guò)程中,往往需要對(duì)當(dāng)前的測(cè)試樣例和注解進(jìn)行驗(yàn)證,比如檢查測(cè)試類是否含有非靜態(tài)內(nèi)部類,測(cè)試類是否是的。的驗(yàn)證機(jī)制非常精致而優(yōu)美,在本次博客中我們就主要來(lái)談一談機(jī)制的實(shí)現(xiàn)。首先在中定義三個(gè)默認(rèn)的類,如下。

前言

在建立Runner的過(guò)程中,往往需要對(duì)當(dāng)前的測(cè)試樣例和注解進(jìn)行驗(yàn)證,比如檢查測(cè)試類是否含有非靜態(tài)內(nèi)部類,測(cè)試類是否是Public的。Junit的驗(yàn)證機(jī)制非常精致而優(yōu)美,在本次博客中我們就主要來(lái)談一談Validator機(jī)制的實(shí)現(xiàn)。

指定一個(gè)驗(yàn)證器

首先我們可以使用注解來(lái)指定某一個(gè)用戶自定義Validator來(lái)進(jìn)行驗(yàn)證,下面給出AnnotationValidator的父類以及相應(yīng)注解。

@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface ValidateWith {
   Class value();
}
public abstract class AnnotationValidator {

    private static final List NO_VALIDATION_ERRORS = emptyList();

    public List validateAnnotatedClass(TestClass testClass) {
        return NO_VALIDATION_ERRORS;
    }

    public List validateAnnotatedField(FrameworkField field) {
        return NO_VALIDATION_ERRORS;

    }

    public List validateAnnotatedMethod(FrameworkMethod method) {
        return NO_VALIDATION_ERRORS;
    }
}

以上可以很清楚地看出ValidateWith注解會(huì)指定相關(guān)的用戶自定義Validator。AnnotationValidator是真正執(zhí)行驗(yàn)證操作的單元,至于這些Validator的Validate方法在何時(shí)調(diào)用,我們會(huì)在文章的最后一部分講解。

對(duì)一個(gè)類進(jìn)行驗(yàn)證

從上面的代碼可以看出一個(gè)Validator需要實(shí)現(xiàn)三方面的驗(yàn)證——對(duì)類的驗(yàn)證、對(duì)方法的驗(yàn)證、對(duì)域的驗(yàn)證,Junit使用職責(zé)鏈模式來(lái)提供了三方面的驗(yàn)證。

首先在AnnotationsValidator中定義三個(gè)默認(rèn)的Validator類,如下。

  private static class ClassValidator extends AnnotatableValidator {
        @Override
        Iterable getAnnotatablesForTestClass(TestClass testClass) {
            return singletonList(testClass);
        }

        @Override
        List validateAnnotatable(
                AnnotationValidator validator, TestClass testClass) {
            return validator.validateAnnotatedClass(testClass);
        }
    }

    private static class MethodValidator extends
            AnnotatableValidator {
        @Override
        Iterable getAnnotatablesForTestClass(
                TestClass testClass) {
            return testClass.getAnnotatedMethods();
        }

        @Override
        List validateAnnotatable(
                AnnotationValidator validator, FrameworkMethod method) {
            return validator.validateAnnotatedMethod(method);
        }
    }

    private static class FieldValidator extends
            AnnotatableValidator {
        @Override
        Iterable getAnnotatablesForTestClass(TestClass testClass) {
            return testClass.getAnnotatedFields();
        }

        @Override
        List validateAnnotatable(
                AnnotationValidator validator, FrameworkField field) {
            return validator.validateAnnotatedField(field);
        }
    }

然后依次調(diào)用這三種Validator

private static final List> VALIDATORS = Arrays.>asList(
            new ClassValidator(), new MethodValidator(), new FieldValidator());

    /**
     * Validate all annotations of the specified test class that are be
     * annotated with {@link ValidateWith}.
     * 
     * @param testClass
     *            the {@link TestClass} that is validated.
     * @return the errors found by the validator.
     */
    public List validateTestClass(TestClass testClass) {
        List validationErrors= new ArrayList();
        for (AnnotatableValidator validator : VALIDATORS) {
            List additionalErrors= validator
                    .validateTestClass(testClass);
            validationErrors.addAll(additionalErrors);
        }
        return validationErrors;
    }

我們可以看到ClassValidator等都繼承自AnnotatableValidator,而且在真正驗(yàn)證的時(shí)候調(diào)用的是它們的validateTestClass方法。它們其實(shí)也并非驗(yàn)證的真正執(zhí)行單元,它們首先找到相應(yīng)TestClass的所有對(duì)應(yīng)層面的注解,然后看這些注解是否是ValidateWith類型,是的話則由類的內(nèi)置工廠來(lái)提供具體的AnnotationValidator。詳細(xì)情況我們?cè)谙乱恍」?jié)中描述。

擴(kuò)展與默認(rèn)的結(jié)合——漂亮的工廠

首先我們給出AnnotationValidatorFactory的定義

public class AnnotationValidatorFactory {
    private static final ConcurrentHashMap VALIDATORS_FOR_ANNOTATION_TYPES =
            new ConcurrentHashMap();

    public AnnotationValidator createAnnotationValidator(ValidateWith validateWithAnnotation) {
        AnnotationValidator validator = VALIDATORS_FOR_ANNOTATION_TYPES.get(validateWithAnnotation);
        if (validator != null) {
            return validator;
        }

        Class clazz = validateWithAnnotation.value();
        try {
            AnnotationValidator annotationValidator = clazz.newInstance();
            VALIDATORS_FOR_ANNOTATION_TYPES.putIfAbsent(validateWithAnnotation, annotationValidator);
            return VALIDATORS_FOR_ANNOTATION_TYPES.get(validateWithAnnotation);
        } catch (Exception e) {
            throw new RuntimeException("Exception received when creating AnnotationValidator class " + clazz.getName(), e);
        }
    }

}

工廠通過(guò)一個(gè)線程安全的Map存儲(chǔ)注解和對(duì)應(yīng)的實(shí)際AnnotationValidator實(shí)例,而AnnotableValidator內(nèi)置通過(guò)內(nèi)置一個(gè)工廠來(lái)存儲(chǔ)所有對(duì)應(yīng)層級(jí)的驗(yàn)證器實(shí)例,并調(diào)用這些驗(yàn)證器對(duì)應(yīng)層級(jí)的驗(yàn)證方法來(lái)返回可能的異常,我們下面貼出該內(nèi)部類的代碼:

private static abstract class AnnotatableValidator {
        private static final AnnotationValidatorFactory ANNOTATION_VALIDATOR_FACTORY = new AnnotationValidatorFactory();

        abstract Iterable getAnnotatablesForTestClass(TestClass testClass);

        abstract List validateAnnotatable(
                AnnotationValidator validator, T annotatable);

        public List validateTestClass(TestClass testClass) {
            List validationErrors= new ArrayList();
            for (T annotatable : getAnnotatablesForTestClass(testClass)) {
                List additionalErrors= validateAnnotatable(annotatable);
                validationErrors.addAll(additionalErrors);
            }
            return validationErrors;
        }

        private List validateAnnotatable(T annotatable) {
            List validationErrors= new ArrayList();
            for (Annotation annotation : annotatable.getAnnotations()) {
                Class annotationType = annotation
                        .annotationType();
                ValidateWith validateWith = annotationType
                        .getAnnotation(ValidateWith.class);
                if (validateWith != null) {
                    AnnotationValidator annotationValidator = ANNOTATION_VALIDATOR_FACTORY
                            .createAnnotationValidator(validateWith);
                    List errors= validateAnnotatable(
                            annotationValidator, annotatable);
                    validationErrors.addAll(errors);
                }
            }
            return validationErrors;
        }
    }

可以說(shuō)這個(gè)帶工廠的內(nèi)部類是一處神來(lái)之筆,整個(gè)流程是AnnotationsValidator類的validateTestClass方法依次調(diào)用職責(zé)鏈中三個(gè)層級(jí)的AnnotatableValidator,它們先找出所有對(duì)應(yīng)層次上的注解,再濾掉那些不是ValidateWith類型的注解,然后通過(guò)一個(gè)工廠來(lái)維護(hù)所有驗(yàn)證器實(shí)例,調(diào)用這些實(shí)例來(lái)真正驗(yàn)證。因?yàn)閷?duì)于不同的TestClass,我們?cè)谝粋€(gè)層面上只用維護(hù)一個(gè)工廠。使用內(nèi)部類,只暴露應(yīng)該暴露的,擴(kuò)展的用戶只應(yīng)擴(kuò)展自定義的Validator,不應(yīng)該在層次邏輯上進(jìn)行擴(kuò)展,不應(yīng)該在整體驗(yàn)證的AnnotationsValidator之外再使用任何多帶帶層次的AnnotatableValidator。

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

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/65451.html

相關(guān)文章

  • Junit源碼閱讀(一)

    摘要:是對(duì)測(cè)試樣例的建模,用來(lái)組合多個(gè)測(cè)試樣例,是中的核心內(nèi)容。也是一個(gè)虛類,子類應(yīng)該實(shí)現(xiàn)方法來(lái)決定對(duì)于是否運(yùn)行。如下列代碼所示組合了和,為運(yùn)行時(shí)異常和斷言錯(cuò)誤屏蔽了不一致的方面,可以向上提供錯(cuò)誤信息和樣例信息。 Junit的工程結(jié)構(gòu) showImg(/img/bVsEeS); 從上圖可以清楚的看出Junit大致分為幾個(gè)版塊,接下來(lái)一一簡(jiǎn)略介紹這些版塊的作用。 runner:定義了Jun...

    Gilbertat 評(píng)論0 收藏0
  • Junit源碼閱讀(四)自定義擴(kuò)展

    摘要:前言上次的博客中我們著重介紹了的機(jī)制,這次我們將聚焦到自定義擴(kuò)展上來(lái)。在很多情形下我們需要在測(cè)試過(guò)程中加入一些自定義的動(dòng)作,這些就需要對(duì)進(jìn)行包裝,為此提供了以接口和為基礎(chǔ)的擴(kuò)展機(jī)制。 前言 上次的博客中我們著重介紹了Junit的Validator機(jī)制,這次我們將聚焦到自定義擴(kuò)展Rule上來(lái)。在很多情形下我們需要在測(cè)試過(guò)程中加入一些自定義的動(dòng)作,這些就需要對(duì)statement進(jìn)行包裝,...

    Little_XM 評(píng)論0 收藏0
  • Junit源碼閱讀(六)Junit設(shè)計(jì)模式

    摘要:前言在這次的博客中我們將著重于的許多集成性功能來(lái)討論中的種種設(shè)計(jì)模式。裝飾器模式裝飾器模式是為了在原有功能上加入新功能,在中絕對(duì)屬于使用最頻繁架構(gòu)中最核心的模式,等都是通過(guò)裝飾器模式來(lái)完成擴(kuò)展的。 前言 在這次的博客中我們將著重于Junit的許多集成性功能來(lái)討論Junit中的種種設(shè)計(jì)模式??梢哉f(shuō)Junit的實(shí)現(xiàn)本身就是GOF設(shè)計(jì)原則的范例教本,下面就讓我們開(kāi)始吧。 裝飾器模式 裝飾器...

    jlanglang 評(píng)論0 收藏0
  • @angular/forms 源碼解析 Validators

    摘要:校驗(yàn)器運(yùn)行完成后,會(huì)設(shè)置屬性,從而計(jì)算的屬性,假設(shè)校驗(yàn)錯(cuò)誤,則屬性值為。這樣就理解了校驗(yàn)器的整個(gè)運(yùn)行過(guò)程,也包括為何校驗(yàn)錯(cuò)誤時(shí)會(huì)自動(dòng)添加描述控件狀態(tài)的。 我們知道,@angular/forms 包主要用來(lái)解決表單問(wèn)題的,而表單問(wèn)題非常重要的一個(gè)功能就是表單校驗(yàn)功能。數(shù)據(jù)校驗(yàn)非常重要,不僅僅前端在發(fā)請(qǐng)求給后端前需要校驗(yàn)數(shù)據(jù),后端對(duì)前端發(fā)來(lái)的數(shù)據(jù)也需要校驗(yàn)其有效性和邏輯性,尤其在存入數(shù)據(jù)庫(kù)...

    JowayYoung 評(píng)論0 收藏0
  • Junit源碼閱讀(五)

    摘要:的作用是包裝從生成的邏輯,提供兩種方案生成和。最后從生成也異常簡(jiǎn)單,也就是實(shí)現(xiàn)其方法返回該。 前言 盡管在第二次博客中我們講述了Runner的運(yùn)行機(jī)制,但是許多其他特性比如Filter是如何與運(yùn)行流程結(jié)合卻并不清楚。這次我們來(lái)回顧整理一下Junit的執(zhí)行流程,給出各種特性生效的機(jī)理,并分析一些代碼中精妙的地方。 Junit的執(zhí)行流程 JUnitCore的RunMain方法,使用jUn...

    vpants 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<