Акка: рекомендации супервайзера по тестированию

Я очень новичок в Akka и используя Java чтобы запрограммировать мою систему.

Определение проблемы
- У меня есть TenantMonitor который, когда получает TenantMonitorMessage()начинается новый актер DiskMonitorActor,
- DiskMonitorActor может потерпеть неудачу по разным причинам и может бросить DiskException, DiskMonitorActor был проверен модулем.

Что мне нужно?
- хочу проверить поведение TenantMonitorActorтак что когда DiskException случается, он принимает правильное действие, как stop(), resume() или любой (в зависимости от того, что может понадобиться моему заявлению)

Что я пробовал?
Основываясь на документации, ближе всего я смог выполнить раздел под названием " Ожидание сообщений журнала".

Где мне нужна помощь?
- Хотя я понимаю, что важно ожидать правильного журнала ошибок, он только утверждает первую часть, что исключение выдается и регистрируется правильно, но не помогает в утверждении этого права. strategy называется

Код?
TenantMonitorActor

public class TenantMonitorActor extends UntypedActor {

  public static final String DISK_MONITOR = "diskMonitor";
  private static final String assetsLocationKey = "tenant.assetsLocation";
  private static final String schedulerKey = "monitoring.tenant.disk.schedule.seconds";
  private static final String thresholdPercentKey = "monitoring.tenant.disk.threshold.percent";

  private final LoggingAdapter logging = Logging.getLogger(getContext().system(), this);
  private final Config config;

  private TenantMonitorActor(final Config config) {
    this.config = config;
  }

  private static final SupervisorStrategy strategy =
      new OneForOneStrategy(1, Duration.create(1, TimeUnit.SECONDS),
                            new Function<Throwable, Directive>() {

                              public Directive apply(final Throwable param) throws Exception {
                                if (param instanceof DiskException) {
                                  return stop();
                                }
                                return restart();
                              }
                            });

  public static Props props(final Config config) {
    return Props.create(new Creator<TenantMonitorActor>(){
      public TenantMonitorActor create() throws Exception {
        return new TenantMonitorActor(config);
      }
    });
  }

  @Override
  public void onReceive(final Object message) throws Exception {
    if (message instanceof TenantMonitorMessage) {
      logging.info("Tenant Monitor Setup");
      setupDiskMonitoring();
    }
  }

  @Override
  public SupervisorStrategy supervisorStrategy() {
    return strategy;
  }



  private void setupDiskMonitoring() {
    final ActorRef diskMonitorActorRef = getDiskMonitorActorRef(config);

    final FiniteDuration start = Duration.create(0, TimeUnit.SECONDS);
    final FiniteDuration recurring = Duration.create(config.getInt(schedulerKey),
                                                     TimeUnit.SECONDS);

    final ActorSystem system = getContext().system();
    system.scheduler()
        .schedule(start, recurring, diskMonitorActorRef,
                  new DiskMonitorMessage(), system.dispatcher(), null);
  }

  private ActorRef getDiskMonitorActorRef(final Config monitoringConf) {
    final Props diskMonitorProps =
        DiskMonitorActor.props(new File(monitoringConf.getString(assetsLocationKey)),
                               monitoringConf.getLong(thresholdPercentKey));
    return getContext().actorOf(diskMonitorProps, DISK_MONITOR);

  }
}

Тестовое задание

  @Test
  public void testActorForNonExistentLocation() throws Exception {
    final Map<String, String> configValues =
        Collections.singletonMap("tenant.assetsLocation", "/non/existentLocation");
    final Config config = mergeConfig(configValues);

    new JavaTestKit(system) {{
      assertEquals("system", system.name());

      final Props props = TenantMonitorActor.props(config);
      final ActorRef supervisor = system.actorOf(props, "supervisor");
      new EventFilter<Void>(DiskException.class) {

        @Override
        protected Void run() {
          supervisor.tell(new TenantMonitorMessage(), ActorRef.noSender());
          return null;
        }
      }.from("akka://system/user/supervisor/diskMonitor").occurrences(1).exec();

    }};
  }

ОБНОВИТЬ
Лучшее, что я мог написать, это убедиться, что DiskMonitor останавливается после возникновения исключения

@Test
  public void testSupervisorForFailure() {
    new JavaTestKit(system) {{

      final Map<String, String> configValues =
          Collections.singletonMap("tenant.assetsLocation", "/non/existentLocation");
      final Config config = mergeConfig(configValues);

      final TestActorRef<TenantMonitorActor> tenantTestActorRef = getTenantMonitorActor(config);
      final ActorRef diskMonitorRef = tenantTestActorRef.underlyingActor().getContext()
          .getChild(TenantMonitorActor.DISK_MONITOR);

      final TestProbe testProbeDiskMonitor = new TestProbe(system);
      testProbeDiskMonitor.watch(diskMonitorRef);
      tenantTestActorRef.tell(new TenantMonitorMessage(), getRef());
      testProbeDiskMonitor.expectMsgClass(Terminated.class);
    }};
  }

Есть ли лучшие способы?

1 ответ

У меня такое ощущение, что тестирование стратегии супервизора - это некая серая область - это личное мнение, когда мы начинаем тестировать саму Akka, а не понимание того, как работает фреймворк. Проверка валидации сущностей в средах ORM кажется мне похожей проблемой. Мы не хотим проверять правильность логики проверки электронной почты (например, в Hibernate), а скорее, правильно ли объявлено наше правило.

Следуя этой логике, я бы написал тест следующим образом:

final TestActorRef<TenantMonitorActor> tenantTestActorRef =
  getTenantMonitorActor(config);
SupervisorStrategy.Directive directive = tenantTestActorRef.underlyingActor()
  .supervisorStrategy().decider().apply(new DiskException());
assertEquals(SupervisorStrategy.stop(), directive);
Другие вопросы по тегам