Модульное тестирование дочерних рабочих процессов Amazon SWF

У меня есть родительский рабочий процесс (ParentWorkflow), вызывающий дочерний рабочий процесс (ChildWorkflow), и я пытаюсь проверить вызов.

Родительский код выглядит примерно так:

public class ParentWorkflow {
    private final ChildWorkflowClientFactory childWorkflowClientFactory =
            new ChildWorkflowClientFactoryImpl();

    public void runWorkflow() {
        new TryCatch() {
            @Override
            protected void doTry() throws Throwable {
                Promise<Void> workflowFinished = childWorkflowClient.childWorkflow(x);
                ...
            }
        ...
    }
}

Я хочу смоделировать вызов childWorkflowClient.childWorkflow(x), однако, когда я подключаю модульный тест, у меня, похоже, нет возможности внедрить клиентскую фабрику, код модульного теста выглядит так:

@Rule
public WorkflowTest workflowTest = new WorkflowTest();
@Mock
private Activities mockActivities;

private ParentWorkflowClientFactory workflowFactory
        = new ParentWorkflowClientFactoryImpl();

@Before
public void setUp() throws Exception {
    // set up mocks
    initMocks(this);

    workflowTest.addActivitiesImplementation(mockActivities);
    workflowTest.addWorkflowImplementationType(ParentWorkflowImpl.class);
    workflowTest.addWorkflowImplementationType(ChildWorkflowImpl.class);

Кажется, я не могу ничего передать в классы реализации рабочего процесса, есть ли другой способ высмеять дочерний рабочий процесс?


person Allan5    schedule 27.05.2015    source источник


Ответы (2)


Вы можете тестировать код рабочего процесса напрямую, имитируя его зависимости, без использования workflowTest:

/**
 * Rule is still needed to initialize asynchronous framework.
 */
@Rule
public WorkflowTest workflowTest = new WorkflowTest();
@Mock
private ActivitiesClient mockActivities;
@Mock
private BWorkflowClientFactory workflowFactory;


@Before
public void setUp() throws Exception {
  // set up mocks
  initMocks(this);
}

@Test
public void myTest() {
  AWorkflowImpl w = new AWorkflowImpl(workflowFactory);
  w.execute(); // whatever execute method of the workflow
}

Такой подход позволяет тестировать части рабочего процесса, инкапсулированные в другие объекты, а не весь рабочий процесс.

Если по какой-либо причине (например, вы используете другую среду тестирования, отличную от JUnit) вы не хотите полагаться на асинхронный код WorkflowTest @Rule, всегда можно выполнить с помощью AsyncScope:

@Test
public void asyncTest() {
   AsyncScope scope = new AsyncScope() {
      protected void doAsync() {
         // Any asynchronous code
         AWorkflowImpl w = new AWorkflowImpl(workflowFactory);
         w.execute(); // whatever execute method of the workflow
      }
   };
   scope.eventLoop();
}
person Maxim Fateev    schedule 28.05.2015
comment
Спасибо за ответ! Это было очень близко к работе, но код, который я хочу протестировать в родительском рабочем процессе, окружен блоком TryCatch и, похоже, не выполняется. Любые идеи, как вызвать код там? Я полагаю, что мог бы просто вывести его в отдельный блок кода и протестировать его, но было бы неплохо, если бы я мог протестировать его непосредственно в исходном контексте. - person Allan5; 28.05.2015
comment
Лучший способ выяснить, где застрял асинхронный код, — использовать метод AsyncScope.getAsynchronousThreadDumpAsString. Он покажет дамп асинхронного стека, в котором указана трассировка асинхронного стека для каждой невыполненной задачи. Не глядя на код, сложно дать более конкретный ответ. - person Maxim Fateev; 28.05.2015
comment
Кстати, если вы используете WorkflowTest и указываете время ожидания для теста, дамп асинхронного потока создается автоматически. - person Maxim Fateev; 28.05.2015
comment
Обновили приведенный выше код, чтобы показать, что происходит, но после небольшой настройки обнаружил, что AsyncScope, который вы предложили выше, решает проблему, спасибо за помощь. - person Allan5; 29.05.2015

РЕДАКТИРОВАТЬ: приведенное ниже относится только к SpringWorkflowTest; WorkflowTest по какой-то причине не имеет addWorkflowImplementation.

Правильным способом использования WorkflowTest было бы добавить фиктивную реализацию дочернего рабочего процесса, а не фактический тип:

@Rule
public SpringWorkflowTest workflowTest = new SpringWorkflowTest();
@Mock
private Activities mockActivities;
@Mock
private ChildWorkflow childWorkflowMock;

private ParentWorkflowClientFactory workflowFactory
        = new ParentWorkflowClientFactoryImpl();

@Before
public void setUp() throws Exception {
    // set up mocks
    initMocks(this);

    workflowTest.addActivitiesImplementation(mockActivities);
    workflowTest.addWorkflowImplementationType(ParentWorkflowImpl.class);
    workflowTest.addWorkflowImplementation(childWorkflowMock);
    ...
}

Затем фреймворк будет вызывать этот макет вместо фактической реализации, когда вы используете фабрику.

person stickyShift    schedule 10.05.2018
comment
Какую версию SDK вы используете? Для WorkflowTest такого метода addWorkflowImplementation не существует. - person jayjyli; 18.07.2018
comment
Плохо - я смотрел SpringWorkflowTest, в котором есть addWorkflowImplementation: docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/ - person stickyShift; 18.07.2018
comment
О, понял, извините, я не видел, что вы использовали Spring в своем фрагменте. - person jayjyli; 19.07.2018