Assertj断言生成器

通过一个简单的命令行工具,第三方的插件Maven插件gradle,使用断言生成器创建特定于您自己的类的断言。

比如说有一个Player类,有name,team和teamMaster属性:

public class Player {

  private String name;
  private String team;
  private List<String> teamMates;

  // 构造函数和setter方法省略
  public String getName() {
    return name;
  }
  public String getTeam() {
    return team;
  }
  public List<String> getTeamMates() {
    return teamMates;
  }

  @Override
  public String toString() {
    return "Player[name="+name+"]";
  }
}

创建一个有hasName(),hasTeam()的PlayerAssert断言类之后可以这样用:

assertThat(mj).hasName("Michael Jordan")
              .hasTeam("Chicago Bulls")
              .hasTeamMates("Scottie Pippen", "Tony Kukoc");

一个失败的断言错误消息会反映出所检查的属性,例如:如果hasName失败,你会得到错误的信息:

Expecting name of:
  <Player[name=Air Jordan]>
to be:
  <Michael Jordan>
but was:
  <Air Jordan>

创建断言

生成器可以为每个属性和公共的字段创建断言,创建出来的断言是特定的属性/断言类型,下面列表显示了断言给定类型的创建:

  • boolean:
    • isX()
    • isNotX()
  • int, long, short, byte, char :
    • hasX(value) - 用==做value的比较
  • float and double:
    • hasX(value) - 用==做value的比较
    • hasXCloseTo(value, delta), diff < delta check
  • Iterable and T[]:
    • hasX(T... values)
    • hasOnlyX(T... values)
    • doesNotHaveX(T... values)
    • hasNoX() 元素的比较是用equalse()方法
  • Object:
    • hasX(value)基于equalse比较

生成器内部会检查属性和公共字段,大多数具体的字段类型都是在生成断言时选择的,对象断言是默认的选择. double和Double会生成同样类型的断言,唯一的区别是他们的比较用的是:==或者equals 你也可以更改模板来修改断言的产生,模板位于模板目录.

例子

public class Player {
  // 公共的属性是没有get,set方法的
  // 私有属性的get和set方法省略

  public String name; // 生成对象断言
  private int age; // 生成整数断言
  private double height; // 生成小数断言
  private boolean retired; // 生成boolean断言
  private List<String> teamMates;  // 生成Iterable断言
}

创建断言

public class PlayerAssert extends AbstractAssert<PlayerAssert, Player> {


  public PlayerAssert hasAge(int age) { ... }

  public PlayerAssert hasHeight(double height) { ... }

  public PlayerAssert hasHeightCloseTo(double height, double offset) { ... }

  public PlayerAssert hasTeamMates(String... teamMates) { ... }

  public PlayerAssert hasOnlyTeamMates(String... teamMates) { ... }

  public PlayerAssert doesNotHaveTeamMates(String... teamMates) { ... }

  public PlayerAssert hasNoTeamMates() { ... }

  public PlayerAssert isRetired() { ... }

  public PlayerAssert isNotRetired() { ... }

  public PlayerAssert hasName(String name) { ... }

  public PlayerAssert(Player actual) {
    super(actual, PlayerAssert.class);
  }

  public static PlayerAssert assertThat(Player actual) {
    return new PlayerAssert(actual);
  }
}

生成切入点(entry point)类 生成器还可以创建入口类,比如Assertions,BddAssertiions和SoftAssertions/JUnitSoftAssertions简化访问每个生成的*Assert类 比如说,例如,该生成器已被应用在Player和Game类,它会创建PlayerAssert和GameAssert类,并且有一个Assertions看起来像:

public class Assertions {

  /**
   * 创建一个新的实例 <code>{@link GameAssert}</code>.

   */
  public static GameAssert assertThat(Game actual) {
    return new GameAssert(actual);
  }

  /**
   * 创建一个新的实例 <code>{@link PlayerAssert}</code>.

   */
  public static PlayerAssert assertThat(Player actual) {
    return new PlayerAssert(actual);
  }

  /**
   * 创建一个新的实例<code>{@link Assertions}</code>.
   */
  protected Assertions() {
    // empty
  }
}

现在你只需要导入org.player.Assertions.assertThat就可以做断言了: import static org.player.Assertions.assertThat;

assertThat(mj).hasName("Michael Jordan")
              .hasTeam("Chicago Bulls")
              .hasTeamMates("Scottie Pippen", "Tony Kukoc");

断言模板

任何一种模板断言类或者切入点模板,都可以用断言模板来生成.模板位于这里 下面是一个用模板生成Player的hasName(String name)方法的断言

/**
 * 校验实际${class_to_assert}类的 ${property}属性是不是等于给定的值.
 * @param ${property_safe}  ${property}方法会比较 ${class_to_assert}类的 ${property}属性的值.
 * @return 断言类.
 * @throws AssertionError - 如果实际的 ${class_to_assert}类的${property}属性不等于给定的参数${throws_javadoc}就抛出这个异常
 */
public ${self_type} has${Property}(${propertyType} ${property_safe}) ${throws}{
  //检查实际的Player,因为制作断言不能为null
  isNotNull();

  //覆盖默认的错误消息,更加个性化
  String assertjErrorMessage = "\nExpecting ${property} of:\n  <%s>\nto be:\n  <%s>\nbut was:\n  <%s>";

  // 安全检查
  ${propertyType} actual${Property} = actual.get${Property}();
  if (!Objects.areEqual(actual${Property}, ${property_safe})) {
    failWithMessage(assertjErrorMessage, actual, ${property_safe}, actual${Property});
  }

  // 返回当前断言的引用
  return ${myself};
}

使用下面这些属性生成hasName(String name)断言:

属性 用法 例子
${property} 生成的断言的属性/字段 name
${propertyType} 生成断言的属性/字段的类型 String
${Property} 生成的断言的属性/字段(大写开头) Name
${property_safe} 如果${property}等于java的保留关键字,就会使用${Propertiy} name
${throws} 调用属性的getter抛出的异常(如果有) -
${throws_javadoc} 调用属性的getter抛出的异常的javadoc(如果有) -
${self_type} 声明类名 PlayerAssertion
${class_to_assert} 生成的断言类 Player
${myself} 代表用于执行断言断言类的实例 this

最后生成的断言:

/**
 * 校验实际${class_to_assert}类的 ${property}属性是不是等于给定的值.
 * @param ${property_safe}  ${property}方法会比较 ${class_to_assert}类的 ${property}属性的值.
 * @return 断言类.
 * @throws AssertionError - 如果实际的 ${class_to_assert}类的${property}属性不等于给定的参数${throws_javadoc}就抛出这个异常
 */
public PlayerAssert hasName(String name) {
  //检查实际的Player,因为制作断言不能为null
  isNotNull();

   //覆盖默认的错误消息,更加个性化
  String assertjErrorMessage = "\nExpecting name of:\n  <%s>\nto be:\n  <%s>\nbut was:\n  <%s>";

  // null safe check
  String actualName = actual.getName();
  if (!Objects.areEqual(actualName, name)) {
    failWithMessage(assertjErrorMessage, actual, name, actualName);
  }

     // 返回当前断言的引用
  return this;
}

模板列表

方法断言模板:

方法断言模板文件 用法 例子
has_assertion_template.txt 对象断言 hasName("Joe")
is_assertion_template.txt boolean断言 isRookie()
is_wrapper_assertion_template.txt Boolean断言 isRookie()
has_assertion_template_for_char.txt char类型断言 hasGender('F')
has_assertion_template_for_character.txt Character断言 hasGender('F')
has_assertion_template_for_whole_number.txt int, long, short 和byte类型断言 hasAge(23)
has_assertion_template_for_whole_number_wrapper.txt Integer, Long, Short 和 Byte类型断言 hasAge(23)
has_assertion_template_for_real_number.txt float 和 double类型断言 hasHeight(1.87)
has_elements_assertion_template_for_array.txt|数组类型断言 hasTeamMastes("mj")
has_elements_assertion_template_for_iterable.txt Iterable断言 hasTeamMates("mj")

类断言模板

类方法模板文件 用法
custom_assertion_class_template.txt|断言类框架
custom_abstract_assertion_class_template.txt base assertion class in in hierarchical assertion
custom_hierarchical_assertion_class_template.txt concrete assertion class in in hierarchical assertion

切入点(netry point)模板

切入点(netry point)模板文件 使用
standard_assertions_entry_point_class_template.txt 断言类框架
standard_assertion_entry_point_method_template.txt 像Assertions类中的assertThat()放的切入点模板
bdd_assertions_entry_point_class_template.txt BddAssertions类框架
bdd_assertion_entry_point_method_template.txt template for then method in BddAssertions entry point class
soft_assertions_entry_point_class_template.txt SoftAssertions类框架
soft_assertion_entry_point_method_template.txt template for "soft" assertThat method in SoftAssertions entry point class
junit_soft_assertions_entry_point_class_template.txt JUnitSoftAssertions类框架

布尔型/predicate型断言的属性

${predicate} predicate断言方法名,例如isRookie()
${neg_predicate} negative predicate断言方法名.例如:isNotRookie()
${predicate_for_error_message_part1} 用于构建predicate错误信息的第一部分
${predicate_for_error_message_part2} 用于构建predicate错误信息的第二部分
${negative_predicate_for_error_message_part1} 用于构建negative predicate错误消息的第一部分
${negative_predicate_for_error_message_part2} 用于构建negative predicate错误消息的第二部分
${predicate_for_javadoc} predicate断言方法的javadoc
${negative_predicate_for_javadoc} negative predicate断言方法的javadoc

数组断言的属性: ${elementType}:数组中元素的类型.比如String[]的属性是String型

类断言的属性

${custom_assertion_class} 断言类类名.如:PlayerAssert
${super_assertion_class} used for the super class in hierarchical assertions.
${imports} 导入当前生成的断言类
${package} 断言类的包名

results matching ""

    No results matching ""