Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add assertions for message variables #1195

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ and provide you with a set of assertions you can use to verify your process beha
> [!Note]
> Heads up! We are building a new Java testing library for Camunda 8.6. The new library will replace Zeebe Process Test.
> New features: Access to Camunda's new REST API, official Spring integration, process coverage, improved UX, and more ([ref](https://github.com/camunda/issues/issues/751)).
> Stay tuned for updates. 🚀
> Stay tuned for updates. 🚀

## Prerequisites

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
package io.camunda.zeebe.process.test.assertions;

import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
import static org.assertj.core.api.MapAssert.assertThatMap;

import io.camunda.zeebe.client.api.response.PublishMessageResponse;
import io.camunda.zeebe.process.test.filters.RecordStream;
Expand All @@ -27,7 +28,9 @@
import io.camunda.zeebe.protocol.record.intent.ProcessMessageSubscriptionIntent;
import io.camunda.zeebe.protocol.record.value.MessageStartEventSubscriptionRecordValue;
import io.camunda.zeebe.protocol.record.value.ProcessMessageSubscriptionRecordValue;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
import org.assertj.core.api.AbstractAssert;
Expand All @@ -36,7 +39,7 @@
/** Assertions for {@link PublishMessageResponse} instances */
public class MessageAssert extends AbstractAssert<MessageAssert, PublishMessageResponse> {

private RecordStream recordStream;
private final RecordStream recordStream;

protected MessageAssert(final PublishMessageResponse actual, final RecordStream recordStream) {
super(actual, MessageAssert.class);
Expand Down Expand Up @@ -234,4 +237,51 @@ private List<Long> getProcessInstanceKeysForCorrelatedMessageStartEvent() {
.map(record -> record.getValue().getProcessInstanceKey())
.collect(Collectors.toList());
}

private Map<String, Object> getVariables() {
return StreamFilter.processMessageSubscription(recordStream)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

❌ We should get the variables of the message from the message records.

A process message subscription is only written when a message is correlated to a process instance.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would use StreamFilter.message(recordStream) for this?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. 👍

.withMessageKey(actual.getMessageKey())
.withRejectionType(RejectionType.NULL_VAL)
.stream()
.map(record -> record.getValue().getVariables())
.findFirst()
.orElse(Collections.emptyMap());
}

/**
* Verifies the message has the given variable.
*
* @param name The name of the variable
* @return this ${@link MessageAssert}
*/
public MessageAssert hasVariable(final String name) {
final Map<String, Object> variables = getVariables();
assertThatMap(variables)
.withFailMessage(
"Unable to find variable with name '%s'. Available variables are: %s",
name, variables.keySet())
.containsKeys(name);
return this;
}

/**
* Verifies the message has the given variable with the specified value.
*
* @param name The name of the variable
* @param value The value of the variable
* @return this ${@link MessageAssert}
*/
public MessageAssert hasVariableWithValue(final String name, final Object value) {
hasVariable(name);

final Object actualValue = getVariables().get(name);
assertThat(actualValue)
.withFailMessage(
"The variable '%s' does not have the expected value.%n"
+ "expected: %s%n"
+ "but was: %s",
name, value, actualValue)
.isEqualTo(value);
return this;
}
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

❌ We need to add the API module as a test dependency. The dependency plugin fails with the message:

[INFO] --- maven-dependency-plugin:3.6.1:analyze-only (analyze) @ zeebe-process-test-assertions ---
Error:  Used undeclared dependencies found:
Error:     io.camunda:zeebe-process-test-api:jar:8.6.0-alpha2-rc2-SNAPSHOT:compile
Error:  Non-test scoped test only dependencies found:
Error:     io.camunda:zeebe-process-test-api:jar:8.6.0-alpha2-rc2-SNAPSHOT:compile

Add the following test dependency to the module pom.xml:

<dependency>
      <groupId>io.camunda</groupId>
      <artifactId>zeebe-process-test-api</artifactId>
      <scope>test</scope>
    </dependency>

Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/*
* Copyright © 2021 camunda services GmbH ([email protected])
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.camunda.zeebe.process.test.assertions;

import static org.assertj.core.api.Assertions.assertThatCode;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;

import io.camunda.zeebe.client.api.response.PublishMessageResponse;
import io.camunda.zeebe.process.test.filters.RecordStream;
import io.camunda.zeebe.protocol.record.Record;
import io.camunda.zeebe.protocol.record.RejectionType;
import io.camunda.zeebe.protocol.record.ValueType;
import io.camunda.zeebe.protocol.record.value.ProcessMessageSubscriptionRecordValue;
import java.util.Collections;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;

class MessageAssertTest {

@AfterEach
void afterEach() {
BpmnAssert.resetRecordStream();
}

@Test
void hasVariableWithValueTest() {
PublishMessageResponse result = mock(PublishMessageResponse.class);
doReturn(123L).when(result).getMessageKey();

ProcessMessageSubscriptionRecordValue recordValue =
mock(ProcessMessageSubscriptionRecordValue.class);
doReturn(Collections.singletonMap("key", "value")).when(recordValue).getVariables();
doReturn(123L).when(recordValue).getMessageKey();

Record<ProcessMessageSubscriptionRecordValue> record = mock(Record.class);
doReturn(recordValue).when(record).getValue();
doReturn(ValueType.PROCESS_MESSAGE_SUBSCRIPTION).when(record).getValueType();
doReturn(RejectionType.NULL_VAL).when(record).getRejectionType();

BpmnAssert.initRecordStream(RecordStream.of(() -> Collections.singleton(record)));

BpmnAssert.assertThat(result).hasVariableWithValue("key", "value");

assertThatCode(() -> BpmnAssert.assertThat(result).hasVariableWithValue("foo", "value"))
.isInstanceOf(AssertionError.class)
.hasMessageStartingWith("Unable to find variable with name 'foo'.");

assertThatCode(() -> BpmnAssert.assertThat(result).hasVariableWithValue("key", "value2"))
.isInstanceOf(AssertionError.class)
.hasMessageStartingWith("The variable 'key' does not have the expected value.");
}
}
Loading