Java 朱尼特,莫基托。如何确保抽象类中的方法(模板方法)调用抽象钩子方法?

Java 朱尼特,莫基托。如何确保抽象类中的方法(模板方法)调用抽象钩子方法?,java,mockito,junit4,Java,Mockito,Junit4,我来了: abstract class IdentifiedEntity<E extends IdentifiedEntity> implements Cloneable { ... public void updateWith(E that) { if (this != that) { if (that.isNew()) { throw new IllegalArgumentException("Cannot update with a

我来了:

abstract class IdentifiedEntity<E extends IdentifiedEntity> implements Cloneable {
  ...
  public void updateWith(E that) {
    if (this != that) {
      if (that.isNew()) {
        throw new IllegalArgumentException("Cannot update with a new entity");
      }
      if (this.isNew()) {
        throw new IllegalStateException("Cannot update a new entity");
      }
      if (this.getId() != that.getId()) {
        throw new IllegalArgumentException("IDs do not match");
      }
      doUpdateWith(that);
    }
  }

  abstract void doUpdateWith(E that);
  ...
}

public final class User extends IdentifiedEntity<User> {
  ...
  @Override
  void doUpdateWith(User that) {
    assert that != null;
    this.name = that.name;
    this.email = that.email;
    System.arraycopy(that.password, 0, password, 0, password.length);
    this.enabled = that.enabled;
    this.caloriesPerDayLimit = that.caloriesPerDayLimit;
  }
  ...
}
抽象类标识实现了可克隆性{
...
使用(E)更新公共无效信息{
如果(这个!=那个){
如果(that.isNew()){
抛出新的IllegalArgumentException(“无法使用新实体更新”);
}
if(this.isNew()){
抛出新的非法状态异常(“无法更新新实体”);
}
如果(this.getId()!=that.getId()){
抛出新的IllegalArgumentException(“ID不匹配”);
}
对(那件事)表示怀疑;
}
}
用(E)表示抽象无效;
...
}
公共最终类用户扩展标识性{
...
@凌驾
void doUpdateWith(该用户){
断言!=null;
this.name=that.name;
this.email=that.email;
System.arraycopy(即.password,0,password,0,password.length);
this.enabled=that.enabled;
this.caloriesPerDayLimit=that.caloriesPerDayLimit;
}
...
}
问题是如何使用(…)对
updateWith(…)
进行单元测试,以确保它明确地调用了在子体中实现的抽象
doUpdateWith(…)
(是的,如果我通过了所有检查,那么可以确定)


就是你们

创建一个虚拟子类

class ConcreteEntity extends IdentifiedEntity<ConcreteEntity> {
  @Override
  void doUpdateWith(ConcreteEntity that) {
  }
}

然而,这样的测试是非常特殊的。它不允许您更改方法的实现。

在@CoronA的帮助下,我找到了答案。这是:

@Test
public void updateWith() {
  User user = this.user.clone().setId(100);
  User mock = Mockito.spy(user);
  mock.updateWith(user);
  Mockito.verify(mock).doUpdateWith(user);
}

非常感谢你们

原理是合理的,但这样做不起作用:
verify
只在电影实例上起作用。虚拟子类需要保留一个计数器,用于计算调用方法的频率。这些代码片段不仅是一个想法,而且确实有效!试试你自己。如果
identifiedentity
不调用update,它们就会失败,如果调用update,它们就会成功。哦,我错过了
Mockito.spy
,这实际上是最重要的一点。事实上,你甚至不需要具体的类;您只需执行
sut=Mockito.spy(IdentifiedEntity.class);sut.updateWith(sut);验证(sut)。使用(sut)更新数据。你是对的,但这不是很直观,因为标识是抽象的。莫基托用了很多魔法让它工作。我应该更新我的示例吗?我想我应该添加一条注释,使其更加清晰,并添加“纯间谍”作为替代。如果它有帮助,那么接受我的答案将是很好的;)。
@Test
public void updateWith() {
  User user = this.user.clone().setId(100);
  User mock = Mockito.spy(user);
  mock.updateWith(user);
  Mockito.verify(mock).doUpdateWith(user);
}