【JUnit】AssertJ / AssertJ-DB ~ 基本編 [3] / 時間に関する比較 ~


■ 日付の比較でよく使うメソッド

 * isEqualTo         : 同じ日付の場合
 * isAfter           : その日付以降の場合
 * isAfterOrEqualTo  : 同じ日付又は、その日付以降の場合
 * isBefore          : その日付以前の場合
 * isBeforeOrEqualTo : 同じ日付又は、その日付以前の場合

補足

 * 作成日や更新日の確認には、日時は不確かなので「isAfterOrEqualTo」を使えばいい
  => 以下のサンプルの「createdate」「updatedate」を参照

■ サンプル

サンプルデータ:MySQL

CREATE TABLE IF NOT EXISTS `item` (
  `id` char(8) DEFAULT NULL,
  `name` varchar(100) DEFAULT NULL,
  `price` int(11) DEFAULT NULL,
  `releasedate` datetime DEFAULT NULL,
  `createdate` datetime DEFAULT current_timestamp,
  `updatedate` datetime DEFAULT current_timestamp on update current_timestamp
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

Item.java

import java.sql.Date;
import java.util.Calendar;

public class Item {
  public String id;
  public String name;
  public Long price;
  public Calendar releaseDate;
  public Date createDate;
  public Date updateDate;
}

AssertJDbSample.java

import java.sql.Connection;
import java.sql.Date;
import java.sql.DriverManager;
import java.sql.PreparedStatement;

import com.mysql.jdbc.MysqlErrorNumbers;
import com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException;

public class SampleInsert {

  public static void main(String[] args) {
    try {
      System.out.println("Start");

      SampleInsert.dbAccess();
    } catch (Exception ex) {
      ex.printStackTrace();
    } finally {
      System.out.println("Finished");
    }
  }

  private static void dbAccess() throws Exception {
    int i = 1;
    while (true) {
      String name = "Kevin";
      Date birthDate = Date.valueOf("1973-1-2");
      String empNo = "S0000-000" + i;
      if (!insert(name, birthDate, empNo)) {
        System.out.println("Done " + i);
        break;
      }
      i++;
    }
  }

  private static boolean insert(String name, Date birthDate, String empNo) throws ClassNotFoundException {
    Class.forName("com.mysql.jdbc.Driver");

    try (
        Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/sampledb", "root", "password");
        PreparedStatement statement = connection
            .prepareStatement("INSERT INTO emp(name, birth_date, emp_no) VALUES(?,?,?)");) {
      statement.setString(1, name);
      statement.setDate(2, birthDate);
      statement.setString(3, empNo);
      int number = statement.executeUpdate();
      System.out.println(number);
    } catch (MySQLIntegrityConstraintViolationException ex) {
      if (MysqlErrorNumbers.ER_DUP_ENTRY == ex.getErrorCode()) {
        System.out.println("Re-try");
        return true;
      }
      // 素通り
    } catch (Exception ex) {
      // 素通り
    }
    return false;
  }
}

AssertJDbSampleTest.java

import static org.junit.Assert.*;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;

import static com.ninja_squad.dbsetup.Operations.*;
import static org.assertj.db.api.Assertions.assertThat;

import org.assertj.db.type.DateTimeValue;
import org.assertj.db.type.DateValue;
import org.assertj.db.type.Source;
import org.assertj.db.type.Table;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;

import com.ninja_squad.dbsetup.DbSetup;
import com.ninja_squad.dbsetup.destination.Destination;
import com.ninja_squad.dbsetup.destination.DriverManagerDestination;
import com.ninja_squad.dbsetup.operation.Operation;

/**
 *
 */
public class AssertJDbSampleTest {
  public static final Operation DELETE_ALL = deleteAllFrom("item");

  /**
   * @throws java.lang.Exception
   */
  @BeforeClass
  public static void setUpBeforeClass() throws Exception {
  }

  /**
   * @throws java.lang.Exception
   */
  @AfterClass
  public static void tearDownAfterClass() throws Exception {
  }

  /**
   * @throws java.lang.Exception
   */
  @Before
  public void setUp() throws Exception {
    Operation operation = sequenceOf(DELETE_ALL);

    Destination destination = new DriverManagerDestination("jdbc:mysql://localhost:3306/sampledb", "root", "password");
    DbSetup dbSetup = new DbSetup(destination, operation);
    dbSetup.launch();
  }

  /**
   * @throws java.lang.Exception
   */
  @After
  public void tearDown() throws Exception {
  }

  /**
   * INSERT Test.
   */
  @Test
  public void insertTest() {
    try {
      Calendar targetDate = Calendar.getInstance();
      
      System.out.println("Debug : " + new SimpleDateFormat("yyyy-MM-dd hh:mm:ss SSS").format(targetDate.getTime()));
      int result = AssertJDbSample.insert("X0001", "Apple", 129, targetDate);
      assertEquals(1, result);

      Source source = new Source("jdbc:mysql://localhost:3306/sampledb", "root", "password");
      Table table = new Table(source, "item");

      assertThat(table).hasNumberOfRows(1);
      assertThat(table).row(0).value("id").isEqualTo("X0001");
      assertThat(table).row(0).value("name").isEqualTo("Apple");
      assertThat(table).row(0).value("price").isEqualTo(129);
      assertThat(table).row(0).value("releasedate").isEqualTo(toDateValue(targetDate));
      assertThat(table).row(0).value("createdate").isAfterOrEqualTo(toDateTimeValue(targetDate));
      assertThat(table).row(0).value("updatedate").isAfterOrEqualTo(toDateTimeValue(targetDate));
    } catch (Exception ex) {
      ex.printStackTrace();
      fail("Exception...");
    }
  }

  private static DateValue toDateValue(String targetDateTime) {
    try {
      return new DateValue(targetDateTime);
    } catch (ParseException ex) {
      throw new RuntimeException(ex);
    }
  }
  
  private static DateValue toDateValue(Calendar targetDateTime) {
    SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd"); 

    return toDateValue(simpleDateFormat.format(targetDateTime.getTimeInMillis()));
  }
  
  private static DateTimeValue toDateTimeValue(String targetDateTime) {
    try {
      return new DateTimeValue(targetDateTime);
    } catch (ParseException ex) {
      throw new RuntimeException(ex);
    }
  }
  
  private static DateTimeValue toDateTimeValue(Calendar targetDateTime) {
    SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ss"); 

    return toDateTimeValue(simpleDateFormat.format(targetDateTime.getTimeInMillis()));
  }
}

関連記事

AssertJ / AssertJ-DB ~ 入門編 ~

http://blogs.yahoo.co.jp/dk521123/36157721.html

AssertJ / AssertJ-DB ~ 基本編 [2] / 時間に関する処理 ~

https://blogs.yahoo.co.jp/dk521123/36164701.html

MySQL利用でAssertJ-DB を使った単体テストを行ったら日時でエラーになる

http://blogs.yahoo.co.jp/dk521123/36167284.html