为什么方法在嘲笑后会被执行?

时间:2018-03-26 13:33:44

标签: java junit static mockito

我有以下测试

public class MyclassTest extends JUnitSuite {

  KubernetesClient kubeClient;

  @SuppressWarnings("static-access")
  @BeforeClass
  public static void setup() {
    system = ActorSystem.create();
    KubeDeployment mockKubeDeployment = Mockito.mock(KubeDeployment.class);
    KubeNamespace mockKubeNamespace = Mockito.mock(KubeNamespace.class);
    Deployment deployment = Mockito.mock(Deployment.class);
    Namespace namespace = Mockito.mock(Namespace.class);
    KubernetesClient kubeClient = Mockito.mock(KubernetesClient.class);
    Service serviceTodeploy = new Service("group","artifact","version");
    DeployEnvironment deployEnvironment = new DeployEnvironment();
    deployEnvironment.setName("K8sDeploymentCreatorTest");

    when(mockKubeNamespace.createNamespace(kubeClient, serviceTodeploy)).thenReturn(namespace);
    when(mockKubeDeployment.createDeployment(serviceTodeploy, kubeClient, namespace)).thenReturn(deployment);

  }

这是真正的方法

public class KubeNamespace {
  /**
   * Creates a kubernetes namespace
   * 
   * @param kubeClient
   * @param namespaceName
   * @param labelValue
   * @return
   */
  public static Namespace createNamespace(KubernetesClient kubeClient, Service serviceToDeploy) {
    String namespaceName = serviceToDeploy.getDeployEnvironment().getName();
    Namespace namespace = kubeClient.namespaces().createNew().withNewMetadata().withName(namespaceName)
        .addToLabels(namespaceName, serviceToDeploy.getServiceCoordinates().toString()).endMetadata().done();

    return namespace;
  }

这会在第一次声明时抛出NPE。在调试时,它看起来像在'createNamespace'方法内的某处抛出一个错误。发送给方法的参数都不为null,有些是真实实例,而有些则是模拟对象。问题是为什么方法在被模拟时会被执行?

经过一些调试之后,看起来并不是该方法是gettng执行的,因为我尝试添加另一个只返回字符串的方法,并在规则时使其相同

 when(mockKubeNamespace.someStupidMEthod(kubeClient, serviceTodeploy)).thenReturn("namespace");

实际方法

public static String someStupidMEthod(KubernetesClient kubeClient, Service serviceToDeploy) {
    String namespaceName = serviceToDeploy.getDeployEnvironment().getName();
    return namespaceName;

  }

这仍然返回null,有些东西告诉我它的类被模拟的方式以及对这些方法的静态访问。我不理解它

在以下注释之后,我将静态方法更改为实例方法,并且正在进行这样的调用

when(new KubeNamespace().createNamespace(kubeClient, serviceTodeploy)).thenReturn(namespace);

仍然在同一条线上获得NPE

这是最终代码

public class K8sDeploymentCreatorTest extends JUnitSuite {

  static ActorSystem system;


  @Before
  public  void setup() {
    system = ActorSystem.create();
    KubeDeployment mockKubeDeployment = mock(KubeDeployment.class);
    KubeNamespace mockKubeNamespace = mock(KubeNamespace.class);
    Deployment deployment = Mockito.mock(Deployment.class);
    Namespace namespace = Mockito.mock(Namespace.class);
    KubernetesClient kubeClient = Mockito.mock(KubernetesClient.class);
    Service serviceTodeploy = new Service("group","artifact","version");
    DeployEnvironment deployEnvironment = new DeployEnvironment();
    deployEnvironment.setName("K8sDeploymentCreatorTest");
    serviceTodeploy.setDeployEnvironment(deployEnvironment);
    when(mockKubeNamespace.createNamespace(kubeClient, serviceTodeploy)).thenReturn(namespace);
    when(mockKubeDeployment.createDeployment(serviceTodeploy, kubeClient, namespace)).thenReturn(deployment);

  }


  @AfterClass
  public static void teardown() {
    TestKit.shutdownActorSystem(system);
    system = null;
  }

  @Test
  public void testK8sDeployment() {

    new TestKit(system) {
      {
        final Props props = Props.create(K8sDeploymentCreator.class);
        final ActorRef underTest = system.actorOf(props);
        KubernetesClient kubeClient = Mockito.mock(KubernetesClient.class);
        DeployEnvironment deployEnvironment = new DeployEnvironment();
        deployEnvironment.setName("K8sDeploymentCreatorTest");
        Service serviceTodeploy = new Service("group","artifact","version");
        serviceTodeploy.setDeployEnvironment(deployEnvironment);
        createK8sDeployment msg = new createK8sDeployment(serviceTodeploy, kubeClient);
        underTest.tell(msg, getRef());
        expectMsg(K8sDeploymentComplete.class);
      }
    };
  }

}


public class K8sDeploymentCreator extends AbstractActor {
  private final LoggingAdapter log = Logging.getLogger(getContext().getSystem(), this);


  @Override
  public Receive createReceive() {
    return receiveBuilder().match(createK8sDeployment.class, msg -> {

      KubeNamespace kubenamespace = new KubeNamespace();
      KubeDeployment kubeDeployment = new KubeDeployment();
      Namespace namespace = kubenamespace.createNamespace(msg.kubeClient, msg.service);
      Deployment deployment = kubeDeployment.createDeployment(msg.service, msg.kubeClient, namespace);
      log.info("sending complete depl msg");

      getSender().tell(new K8sDeploymentComplete(deployment), getSelf());
    })
        .matchAny(o -> log.info("received unknown message")).build();
  }

1 个答案:

答案 0 :(得分:1)

这不是正确的方式

when(new KubeNamespace().createNamespace

因为在这里你正在创建一个没有嘲笑的新对象。 在使方法不是静态之后,使用您之前创建的模拟对象 (KubeNamespace mockKubeNamespace = Mockito.mock(KubeNamespace.class);

基本上你的旧'何时'在使createNamespace方法非静态之后,语句应该起作用。

when(mockKubeNamespace.createNamespace(kubeClient, serviceTodeploy)).thenReturn(namespace);