如何测试通过调用 class 调用的委托的交互?

How to test interactions on delegate called by invoking class?

我有如下所示的 类,遗留代码。我想要实现的目标是确保在传递用户数据的情况下调用委托方法 processUser。其次,我还想确保调用传入的 Registration 对象的 doRegister。我的委托在下面显示,但测试没有通过,正如它所说的,调用太少。我正在使用 Groovy spock 测试版本 1.2

class Invoker {
    Delegate delegate;

    Invoker(Delegate delegate) {
        this.delegate = delegate;
    }

    void invoke(UserData user) {
        delegate.processUser(user);
    }
}
class Delegate {
    private RegistrationService service;

    Delegate (RegistrationService r) {
        this.service = r;
    }

    void processUser(UserData data) {
        service.doRegistration(data);
    }
}
class DelegateSpec extends Specification {
     Delegate delegate
     RegistrationService registration
     Invoker invoker

     def setup() {
         registration = Mock()
         delegate = new Delegate(registration)
         Invoker invoker = new Invoker(delegate)
     }

     def "Invoker should invoke delegate passed to it"() {
         given:
         UserData u = ....
         when:
         invoker.invoke(u)
         then:
         1* delegate.processUser(u) 
    }
}

首先让我提供一组完全一致的类以便能够编译应用程序代码:

package de.scrum_master.Whosebug.q59366025;

public class UserData {}
package de.scrum_master.Whosebug.q59366025;

public class RegistrationService {
  public void doRegistration(UserData data) {}
}
package de.scrum_master.Whosebug.q59366025;

class Delegate {
  private RegistrationService service;

  Delegate (RegistrationService r) {
    this.service = r;
  }

  void processUser(UserData data) {
    service.doRegistration(data);
  }
}
package de.scrum_master.Whosebug.q59366025;

class Invoker {
  Delegate delegate;

  Invoker(Delegate delegate) {
    this.delegate = delegate;
  }

  void invoke(UserData user) {
    delegate.processUser(user);
  }
}

现在关于你的测试,你把它变得比必要的更复杂,而且还有一个逻辑错误:

  • 如果 Delegate 不是 mock 或 spy,则无法检查 1 * 之类的交互。
  • 所以只需将其设为 mock,那么您也不再需要注入其 RegistrationService 依赖项 - 这就是创建 mock 的全部意义所在。
package de.scrum_master.Whosebug.q59366025

import spock.lang.Specification

class DelegateSpec extends Specification {
  def delegate = Mock(Delegate)
  def invoker = new Invoker(delegate)

  def "Invoker should invoke delegate passed to it"() {
    given:
    def userData = new UserData()
    when:
    invoker.invoke(userData)
    then:
    1 * delegate.processUser(userData)
  }
}