Mokito with akka actors



我正在使用其Java API和Mockito TestKit进行单位测试的AKKA框架

这是演员

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

这是测试类

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

这将通过NPE(NullPoInterException(失败,试图在CreateNamespace((内执行代码。此方法已被嘲笑,是否应该跳过劝告,然后返回语句说应该返回的任何内容?

这是因为我正在实例化Kubenamspace的新OBJEC以及Kubedeployment作为模拟的触点?

您实际上并未在测试中模仿任何内容。您正在创建模拟对象,但它们没有被注入到正在测试的代码中。您的演员正在执行对消息的响应时执行以下代码:

KubeNamespace kubeNamespace = new KubeNamespace();
KubeDeployment kubeDeployment = new KubeDeployment();

这会创建新的未隔离对象,这些对象将按照编码进行运行 - 并且通常会导致NPE,因为它们没有依赖的外部依赖关系。

如果要模拟以这种方式创建的对象,则必须重构代码以将它们的创建提取到模拟的工厂类中,或者使用更具侵入性的模拟库,例如PowerMock或Jmockit。

工厂模拟的示例

class KubeFactory {
    public KubeNamespace makeNamespace() {
        return new KubeNamespace();
    }
    public KubeDeployment makeDeployment() {
        return new KubeDeployment();
    }
}
public class K8sDeploymentCreator extends AbstractActor {
    private final KubeFactory factory;
    K8sDeploymentCreator() {
        this(new KubeFactory());
    }
    // This constructor allows you to override the factory used for testing
    K8sDeploymentCreator(KubeFactory factory) {
        this.factory = factory;
    }
    @Override
    public Receive createReceive() {
      return receiveBuilder().match(createK8sDeployment.class, msg -> {
          KubeNamespace kubenamespace = factory.makeNamespace();
          KubeDeployment kubeDeployment = factory.makeDeployment();
          // rest is as before...
        });
    }
}

然后在您的测试类中创建一个测试KubeFactory,该测试返回您正在测试的类模拟实例:

@Test
public void testK8sDeployment() {
  new TestKit(system) {
    {
      final KubeFactory mockFactory = mock(KubeFactory.class);
      when(mockFactory.makeNamespace()).thenReturn(mockKubeNamespace);
      when(mockFactory.makeDeployment()).thenReturn(mockKubeDeployment);
      final Props props = Props.create(K8sDeploymentCreator.class, mockFactory);
      final ActorRef underTest = system.actorOf(props);
      // and so on...
    }
  }
}

相关内容

  • 没有找到相关文章

最新更新