1

I have the following test

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);

  }

And here is the real method

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;
  }

This throws an NPE at the first when statement. Upon debugging it looks like it throws an error somewhere inside the 'createNamespace' method. None of the arguments sent to the method are null some are real instances while some are mocked objects. The question is why is the method getting executed if its mocked?

After some more debugging it looks like it is not that the method is gettng executed because I tried adding another method that just returns a string and made the same when rule

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

And the actual method

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

  }

This is still returning a null, something tells me its the way the class is mocked and the static access to these methods. BUt I dont understand it correctly

After the following comments I changed the static methids to instance methods and am making the calls like this

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

Still get the NPE at the same line

Here is the final code

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();
  }
user_mda
  • 18,148
  • 27
  • 82
  • 145

1 Answers1

1

This is not right way

when(new KubeNamespace().createNamespace

Because here you are creating new object which not mocked. After making method not static, use mocked object you created earlier ( KubeNamespace mockKubeNamespace = Mockito.mock(KubeNamespace.class); )

Basically your old 'when' statement should work after making createNamespace method non-static.

when(mockKubeNamespace.createNamespace(kubeClient, serviceTodeploy)).thenReturn(namespace);
Dherik
  • 17,757
  • 11
  • 115
  • 164
ddinde
  • 96
  • 1
  • 9