FlatSpec 在使用 'should contain only' 时显示奇怪的行为

FlatSpec displays strange behaviour while using 'should contain only'

我有一个简单的测试,我测试一个特定的数组是否只包含 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;
  }
}

这些是不同的解决方案。

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

returns item1.setScheme("value2)

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

setScheme("value2")new Item1("value1")和returnsnew 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的类型是Item1(即case class),当你使用{}时,你在Item1里面调用,结果却不是一个String或一个Int,结果是case class。您可以使用 {}case class 内操作,但您总是会收到 case class.

匿名子 class 上的

getClass 不同于基础 class 上的 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
false

我们看到 getClass 两者不同。这使得被覆盖的 Item1.equals 在接下来的检查

中失败
if (obj.getClass().equals(this.getClass())) ...

这使得 ScalaTests 的等式断言失败。