2015-04-01 3 views
2

Я новичок в akka, и я пытаюсь akka на java. Я хотел бы понять модульное тестирование бизнес-логики внутри участников. Я прочитал documentation и единственный пример изолированного бизнес-логики в актера:Единичное тестирование частных методов в Akka

static class MyActor extends UntypedActor { 
    public void onReceive(Object o) throws Exception { 
    if (o.equals("say42")) { 
     getSender().tell(42, getSelf()); 
    } else if (o instanceof Exception) { 
     throw (Exception) o; 
    } 
    } 
    public boolean testMe() { return true; } 
} 

@Test 
public void demonstrateTestActorRef() { 
    final Props props = Props.create(MyActor.class); 
    final TestActorRef<MyActor> ref = TestActorRef.create(system, props, "testA"); 
    final MyActor actor = ref.underlyingActor(); 
    assertTrue(actor.testMe()); 
} 

Хотя это просто, это означает, что метод, который я хочу, чтобы проверить, является достоянием общественности. Однако, учитывая, что субъекты должны общаться только через сообщения, я понимаю, что нет оснований для публичных методов, поэтому я сделал свой метод приватным. Как и в примере ниже:

public class LogRowParser extends AbstractActor { 
    private final Logger logger = LoggerFactory.getLogger(LogRowParser.class); 

    public LogRowParser() { 
     receive(ReceiveBuilder. 
         match(LogRow.class, lr -> {         
          ParsedLog log = parse(lr.rowText); 
          final ActorRef logWriter = getContext().actorOf(Props.create(LogWriter.class)); 
          logWriter.tell(log, self()); 
         }). 
         matchAny(o -> logger.info("Unknown message")).build() 
     ); 
    } 

    private ParsedLog parse(String rowText) { 
     // Log parsing logic 
    } 
} 

Так к методу испытаний parse я либо:

  1. нужно это сделать пакет-частного
  2. Или открытый интерфейс тест актера, то есть, что следующий актер LogWriter получил правильный разобранные сообщение от моего актера LogRowParser

Мои вопросы:

  1. Есть ли недостатки в опции №1? Предполагая, что субъекты, общающиеся только через сообщения, инкапсуляция и чистые открытые интерфейсы, менее важны?
  2. В случае, если я попытаюсь использовать опцию № 2, есть ли способ поймать сообщения, отправленные от актера в тесте вниз по течению (тестирование LogRowParser и ловить в LogWriter)? Я рассмотрел различные примеры на JavaTestKit, но все они захватывают сообщения, которые являются ответами отправителю, и ни один из них не показывает, как перехватить сообщение, отправляемое новому актеру.
  3. Есть ли другой вариант, который мне не хватает?

Спасибо!

UPD: Забыл упомянуть, что я также рассмотрел варианты, как:

  • Перемещение логики из актеров полностью в вспомогательные классы. Это обычная практика с аккой?
  • Powermock ... но я пытаюсь избежать, если редизайн возможно

ответ

2

В действительности нет веской причины сделать этот метод приватным. Обычно обычно применяется метод класса private, чтобы кто-то, у которого есть прямая ссылка на экземпляр этого класса, вызывает этот метод. С экземпляром актера никто не будет иметь прямой ссылки на экземпляр этого класса актера. Все, что вы можете связать с экземпляром этого класса актера, - это ActorRef, который является прокси легким весом, который позволяет вам общаться, отправляя сообщения, обрабатываемые onReceive через почтовый ящик. Значение ActorRef не раскрывает никакого внутреннего состояния или методов этого класса актера.Это своего рода одна из больших точек продажи актерской системы. Экземпляр актера полностью инкапсулирует его внутреннее состояние и методы, защищая их от внешнего мира и только позволяет изменять эти внутренние вещи в ответ на получение сообщений. Вот почему нет необходимости отмечать этот метод как закрытый.

Редактировать

Юнит актера, ИМО, всегда должны идти через receive функциональность. Если у вас есть внутренние методы, которые затем вызывается обработкой в ​​receive, вам не следует сосредоточиться на тестировании этих методов изолированно, но вместо этого убедитесь, что пути, которые приводят к их вызову, правильно выполняются через сообщения, которые вы передаете во время тестовых сценариев ,

В вашем конкретном примере parse создает сообщение ParsedLog, которое затем отправляется на дочерний актер logWriter. Для меня, зная, что parse работает как ожидалось, означает, что logWriter получил правильное сообщение. Чтобы сделать это, я разрешил бы переопределить имя дочернего logWriter, а затем сделать это только в тестовом коде и заменить создание актера TestProbe. Затем вы можете использовать expectMsg на этом зонде, чтобы удостовериться, что он получил ожидаемое сообщение ParsedLog, таким образом, также тестируя функциональность в parse.

Что касается вашего другого комментария по поводу перемещения реального бизнеса для актера в отдельный и более проверяемый класс, а затем называть это от актера, некоторые люди делают это, так что это не неслыханно. Я лично этого не делаю, но это только я. Если этот подход работает для вас, я не вижу серьезных проблем с ним.

+0

Большое спасибо за ответ и эту часть в частности. _ ActorRef не раскрывает никакого внутреннего состояния или методов этого класса актера. Это своего рода одна из больших точек продажи актерской системы, она не только отвечает на мой вопрос, но и помогает мне лучше понять актерские модели. –

+0

Вы правы (я проголосовал за ваш ответ), но вы на самом деле не отвечали ни на какие конкретные вопросы. Предполагая, что вы не можете изменить данную кодовую базу, как вы поступите? –

+0

@JamesSharp, я добавил немного более подробно. Я не отвечаю на вопросы напрямую, но я предоставляю то, что, по моему мнению, является обоснованным подходом для тестирования участников. Надеюсь это поможет. – cmbaxter

0

У меня была такая же проблема, 3 года назад, когда дело с актерами: лучший подход я нашел в том, чтобы иметь минимальную ResponsAbility к актер, несущий ответственность. Актер получит сообщение и выберет метод Object для вызова или отправленное сообщение или исключение, и это все. Таким образом, будет очень просто макетировать либо услуги, называемые актером, и входные данные для этих служб.

Смежные вопросы