現象
* MySQLを利用したシステムで、AssertJ-DB を使った単体テストを行ったら 日時でエラーになってしまう
単体試験内容
Calendar targetDate = Calendar.getInstance(); int result = TargetSample3.insert("X0001", "Apple", 129, targetDate); // 略 assertThat(table).row(0).value("releasedate").isEqualTo(new DateTimeValue(targetDate));元ネタは以下の関連記事を参照
http://blogs.yahoo.co.jp/dk521123/36164701.html
エラー内容
Expecting: <2016-06-21T22:41:05.000000000> to be equal to: <2016-06-21T22:41:04.866000000>
原因
http://qiita.com/kamipo/items/fb3f7aff8e08fcd67898より抜粋 MySQL 5.6からDATETIMEは小数点以下が四捨五入(round)される 対して、DateTimeValueはミリ秒まで設定するので不一致となり、エラーと判断されてしまうhttps://github.com/joel-costigliola/assertj-db/blob/master/src/main/java/org/assertj/db/type/TimeValue.java
より抜粋 public TimeValue(Calendar calendar) { if (calendar == null) { throw new NullPointerException("time should be not null"); } hours = calendar.get(Calendar.HOUR_OF_DAY); minutes = calendar.get(Calendar.MINUTE); seconds = calendar.get(Calendar.SECOND); nanoSeconds = calendar.get(Calendar.MILLISECOND) * 1000000; }
対策案
* 期待値をミリ秒を四捨五入して比較する
修正案
http://stackoverflow.com/questions/20385067/how-to-round-off-timestamp-in-milliseconds-to-nearest-secondsを参考に修正。 assertThat(table).row(0).value("releasedate").isEqualTo(toDateTimeValue(targetDate)); // 略 // ミリ秒を四捨五入 private static DateTimeValue toDateTimeValue(Calendar targetDateTime) { DateValue dateValue = new DateValue(targetDateTime); int hour = targetDateTime.get(Calendar.HOUR_OF_DAY); int minute = targetDateTime.get(Calendar.MINUTE); int second = targetDateTime.get(Calendar.SECOND); int milliSecond = targetDateTime.get(Calendar.MILLISECOND); // For MySQL second = second + ((milliSecond + 500) / 1000); TimeValue timeValue = new TimeValue(hour, minute, second); return new DateTimeValue(dateValue, timeValue); }