LoginSignup
1
3

More than 5 years have passed since last update.

Spring カスタムvalidator単体テスト

Last updated at Posted at 2016-08-04

はじめに

  • validatorにはmodelにアノテーションつけるだけで良くね的なチェックもありますが気にせずに。。。
  • 近いうちにSpockで実装する記事を書く!。。。かも。

サンプルvalidator

公式より拝借。ちょっとだけ変える。
9.2 Validation using Spring’s Validator interface

PersonValidator.java
public class PersonValidator implements Validator {
    public boolean supports(Class clazz) {
        return Person.class.equals(clazz);
    }

    public void validate(Object obj, Errors e) {
        Person p = (Person) obj;
        if (p.getAge() < 0) {
            e.rejectValue("age", "negativevalue");
        } else if (p.getAge() > 110) {
            e.rejectValue("age", "too.darn.old");
        }

        ValidationUtils.rejectIfEmpty(e, "name", "name.empty");
        if(!e.hasErrror()) {
            if(p.getName.length() <= MAX_CHARS) {
                e.rejectValue("name", "error.entry.tooManyChars");
            }
        }
    }
}

実装

基底クラス。

PersonValidatorTestBase.java
public class PersonValidatorTestBase {
    protected Person target;
    protected DataBinder binder;

    @Before
    public void 事前処理() {
        // target正常値初期化
        target = new Person();
        target.setAge(10);
        target.setName("valid name");

        // bind
        binder = new DataBinder(target);
        binder.setValidator(new PersonValidator());
    }
}

実装クラス。
ちょっと1つのテストが2つのメソッドに分かれちゃってるのがよくないかな。。まぁ雰囲気つかむのが目的ということで。

PersonValidatorTest.java
@RunWith(Enclosed.class) //--(1)
public class PersonValidatorTest {
    @RunWith(Theories.class) //--(2)
    public static class 年齢テスト extends PersonValidatorTestBase {
        @DataPoints("ok") //--(3)
        public static MutablePropertyValues[] mpvArrOk = {
            new MutablePropertyValues()
                .add("age" , 0)
                .add("description" , "年齢のOK境界値MIN"),
            new MutablePropertyValues()
                .add("age" , 110)
                .add("description" , "年齢のOK境界値MAX")
        };

        @DataPoints("ng")
        public static MutablePropertyValues[] mpvArrNg = {
            new MutablePropertyValues()
                .add("age" , -1)
                .add("description" , "年齢がマイナステスト")
                .add("errCode"     , "negativevalue"),
            new MutablePropertyValues()
                .add("age" , 111)
                .add("description" , "年齢行き過ぎテスト")
                .add("errCode"     , "too.darn.old")
        };

        @Theory //--(4)
        public void アプリ相関チェック_正常系(@FromDataPoints("ok") MutablePropertyValues mpv) {
            binder.bind(mpv); //--(5)
            binder.validate();

            BindingResult br = binder.getBindingResult();
            assertThat(br.hasErrors())
                .as((String)mpv.get("description"))
                .isFalse();
        }

        @Theory
        public void アプリ相関チェック_異常系(@FromDataPoints("ng") MutablePropertyValues mpv) {
            binder.bind(mpv);
            binder.validate();

            // descriptionとerrCodeはちょっと強引
            BindingResult br = binder.getBindingResult();
            assertThat(br.getFieldError("age").getCode())
                .as((String)mpv.get("description"))
                .isEqualTo((String)mpv.get("errCode"));
        }
    }

    @RunWith(Theories.class)
    public static class 名前テスト extends PersonValidatorTestBase {
        // 省略
    }
}

(1) Enclosed.class

  • テスト項目ごとに階層を分けるためのランナー

(2) Theories.class

  • DataPointsなどを使用するためのランナー

(3) @DataPoints(名前)

  • ここで指定した配列分だけテストが繰り返される
  • テスト対象の「フィールド名, 値」でaddしていく
  • フィールドとして定義されていないものもaddできる
    ※今回はdescriptionとadd。これに関してはもっといいやり方知りたい。

(4) @Theory

  • DataPoints使うためのアノテーション。
  • 引数にDataPointsとして定義した型の変数を指定

(5) DataBinder.bind

  • bindによってテスト対象のモデルに値が代入される

参考

JUnit入門その9[@RunWithアノテーションを利用したテストの作成]

1
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
3