FlatSpec在使用“应仅包含”时显示奇怪的行为

时间:2019-05-13 13:08:59

标签: scala contains scalatest

我有一个简单的测试,我测试一个特定的数组是否仅包含2个项目。

testArray should contain only (item1, item2)

item1是一个Java对象,其字段只能通过setter设置,而不能通过构造函数设置。

如果我这样实例化对象1:

val item1 = new Item1("value1")
item1.setScheme("value2)

测试成功表明它确实包含对象。

但是,如果我像这样实例化object1:

val item1 = new Item1("value1") {
   setScheme("value2")
}

测试失败。虽然方案值仍以相同方式设置。 在两种情况下,println(item1)都会导致item1(value='value1', scheme='value2')

有人知道FlatSpec为什么以不同的方式对待这些案件吗?

Item1的代码(出于兼容性原因,将字段重命名)

public class Item1 extends LanguageTokenizedString {
  private static final long serialVersionUID = -8903312231226570431L;
  protected String scheme;

  public Item1() {
  }

  public Item1(String value) {
    super(value);
  }

  public Item1(String value, String language) throws InvalidLanguageTokenException {
    super(value, language);
  }

  public Item1(String value, Locale locale) throws InvalidLanguageTokenException {
    super(value, locale);
  }

  public Item1(String value, String language, String scheme) throws InvalidLanguageTokenException {
    super(value, language);
    this.setScheme(scheme);
  }

  public Item1(String value, Locale locale, String scheme) throws InvalidLanguageTokenException {
    super(value, locale);
    this.setScheme(scheme);
  }

  public String getScheme() {
    return this.scheme;
  }

  public final void setScheme(String scheme) {
    this.scheme = scheme;
  }

  public boolean equals(Object obj) {
    boolean equals = false;
    if (obj != null) {
      if (obj == this) {
        equals = true;
      } else if (obj.getClass().equals(this.getClass())) {
        Item1 other = (Item1)obj;
        equals = (new EqualsBuilder()).append(this.value, other.value).append(this.scheme, other.scheme).append(this.schemeId, other.schemeId).append(this.language, other.language).isEquals();
      }
    }

    return equals;
  }

  public boolean shallowEquals(Object obj) {
    boolean shequals = false;
    if (obj != null) {
      if (obj == this) {
        shequals = true;
      } else if (obj.getClass().equals(this.getClass())) {
        Item1 other = (Item1)obj;
        shequals = (new EqualsBuilder()).append(this.value, other.value).append(this.scheme, other.scheme).append(this.schemeId, other.schemeId).isEquals();
      }
    }

    return shequals;
  }

  public int hashCode() {
    return (new HashCodeBuilder(23, 29)).append(this.value).append(this.scheme).append(this.schemeId).append(this.language).toHashCode();
  }

  public boolean isComplete() {
    return true;
  }
}

2 个答案:

答案 0 :(得分:3)

匿名子类上的

getClass与基类上的getClass不同。例如

val itemA = new Item1("value1")
itemA.setScheme("value2")

val itemB = new Item1("value1") {
  setScheme("value2")
}

println(itemA.getClass)
println(itemB.getClass)
println(itemA.getClass == itemB.getClass)

应输出

class example.Item1
class example.HelloSpec$$anon$1
false

我们看到的getClass两者有所不同。这会使覆盖的Item1.equals在以下检查中失败

if (obj.getClass().equals(this.getClass())) ...

这会使ScalaTests的相等性声明失败。

答案 1 :(得分:1)

这些是不同的解决方案。

val item1 = new Item1("value1")
item1.setScheme("value2)

返回item1.setScheme("value2)

val item1 = new Item1("value1") {
  setScheme("value2")
} 

setScheme("value2")内进行new Item1("value1")并返回new Item1("value1")

示例

case class Item1(a: String){
  def setScheme(a:Int): Int ={
    a
  }
}

val item10: Item1 = new Item1("value1"){
  setScheme(1)
}
item10.a: String
item10.setScheme(1): Int

val item11 = new Item1("value1")
val item2: Int = item11.setScheme(1)
item2

item10的类型为Item1case class),当您使用{}时,您在Item1内调用,但结果不是{ {1}}或String,结果为Int。您可以使用case class{}内部进行操作,但始终可以恢复case class