diff options
author | Antoine Vinot <antoine.vinot@sonarsource.com> | 2022-09-13 10:27:42 +0200 |
---|---|---|
committer | sonartech <sonartech@sonarsource.com> | 2022-09-19 20:03:08 +0000 |
commit | 9d1fe387d11c2f27c8463b7bd05497ee1418c31d (patch) | |
tree | a43a39503f9516a4cdee550084f684b983dadc3a /server/sonar-webserver-api | |
parent | fa0c45f87a15dfca332ff46ab5b3061b5c4c3efa (diff) | |
download | sonarqube-9d1fe387d11c2f27c8463b7bd05497ee1418c31d.tar.gz sonarqube-9d1fe387d11c2f27c8463b7bd05497ee1418c31d.zip |
SONAR-17271 - Add origin on issue update from ALM
Diffstat (limited to 'server/sonar-webserver-api')
6 files changed, 219 insertions, 131 deletions
diff --git a/server/sonar-webserver-api/src/main/java/org/sonar/server/qualitygate/changeevent/ChangedIssueImpl.java b/server/sonar-webserver-api/src/main/java/org/sonar/server/qualitygate/changeevent/ChangedIssueImpl.java new file mode 100644 index 00000000000..4fb7264c4bf --- /dev/null +++ b/server/sonar-webserver-api/src/main/java/org/sonar/server/qualitygate/changeevent/ChangedIssueImpl.java @@ -0,0 +1,117 @@ +/* + * SonarQube + * Copyright (C) 2009-2022 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.qualitygate.changeevent; + +import java.util.Objects; +import org.sonar.api.issue.Issue; +import org.sonar.api.rules.RuleType; +import org.sonar.core.issue.DefaultIssue; + +class ChangedIssueImpl implements QGChangeEventListener.ChangedIssue { + private final String key; + private final QGChangeEventListener.Status status; + private final RuleType type; + private final String severity; + private final boolean fromAlm; + + ChangedIssueImpl(DefaultIssue issue) { + this(issue, false); + } + + ChangedIssueImpl(DefaultIssue issue, boolean fromAlm) { + this.key = issue.key(); + this.status = statusOf(issue); + this.type = issue.type(); + this.severity = issue.severity(); + this.fromAlm = fromAlm; + } + + static QGChangeEventListener.Status statusOf(DefaultIssue issue) { + switch (issue.status()) { + case Issue.STATUS_OPEN: + return QGChangeEventListener.Status.OPEN; + case Issue.STATUS_CONFIRMED: + return QGChangeEventListener.Status.CONFIRMED; + case Issue.STATUS_REOPENED: + return QGChangeEventListener.Status.REOPENED; + case Issue.STATUS_TO_REVIEW: + return QGChangeEventListener.Status.TO_REVIEW; + case Issue.STATUS_IN_REVIEW: + return QGChangeEventListener.Status.IN_REVIEW; + case Issue.STATUS_REVIEWED: + return QGChangeEventListener.Status.REVIEWED; + case Issue.STATUS_RESOLVED: + return statusOfResolved(issue); + default: + throw new IllegalStateException("Unexpected status: " + issue.status()); + } + } + + private static QGChangeEventListener.Status statusOfResolved(DefaultIssue issue) { + String resolution = issue.resolution(); + Objects.requireNonNull(resolution, "A resolved issue should have a resolution"); + switch (resolution) { + case Issue.RESOLUTION_FALSE_POSITIVE: + return QGChangeEventListener.Status.RESOLVED_FP; + case Issue.RESOLUTION_WONT_FIX: + return QGChangeEventListener.Status.RESOLVED_WF; + case Issue.RESOLUTION_FIXED: + return QGChangeEventListener.Status.RESOLVED_FIXED; + default: + throw new IllegalStateException("Unexpected resolution for a resolved issue: " + resolution); + } + } + + @Override + public String getKey() { + return key; + } + + @Override + public QGChangeEventListener.Status getStatus() { + return status; + } + + @Override + public RuleType getType() { + return type; + } + + @Override + public String getSeverity() { + return severity; + } + + @Override + public boolean fromAlm() { + return fromAlm; + } + + @Override + public String toString() { + return "ChangedIssueImpl{" + + "key='" + key + '\'' + + ", status=" + status + + ", type=" + type + + ", severity=" + severity + + ", fromAlm=" + fromAlm + + '}'; + } +} diff --git a/server/sonar-webserver-api/src/main/java/org/sonar/server/qualitygate/changeevent/QGChangeEventListener.java b/server/sonar-webserver-api/src/main/java/org/sonar/server/qualitygate/changeevent/QGChangeEventListener.java index 149e623c64c..919fcbd628a 100644 --- a/server/sonar-webserver-api/src/main/java/org/sonar/server/qualitygate/changeevent/QGChangeEventListener.java +++ b/server/sonar-webserver-api/src/main/java/org/sonar/server/qualitygate/changeevent/QGChangeEventListener.java @@ -53,6 +53,10 @@ public interface QGChangeEventListener { default boolean isVulnerability() { return getType() == VULNERABILITY; } + + default boolean fromAlm() { + return false; + } } enum Status { diff --git a/server/sonar-webserver-api/src/main/java/org/sonar/server/qualitygate/changeevent/QGChangeEventListeners.java b/server/sonar-webserver-api/src/main/java/org/sonar/server/qualitygate/changeevent/QGChangeEventListeners.java index 78d51c8cc6e..192db74ef2d 100644 --- a/server/sonar-webserver-api/src/main/java/org/sonar/server/qualitygate/changeevent/QGChangeEventListeners.java +++ b/server/sonar-webserver-api/src/main/java/org/sonar/server/qualitygate/changeevent/QGChangeEventListeners.java @@ -25,5 +25,11 @@ import org.sonar.core.issue.DefaultIssue; public interface QGChangeEventListeners { - void broadcastOnIssueChange(List<DefaultIssue> changedIssues, Collection<QGChangeEvent> qgChangeEvents); + /** + * Broadcast events after issues were updated + * + * @param fromAlm: true if issues changes were initiated by an ALM. + */ + void broadcastOnIssueChange(List<DefaultIssue> changedIssues, Collection<QGChangeEvent> qgChangeEvents, boolean fromAlm); + } diff --git a/server/sonar-webserver-api/src/main/java/org/sonar/server/qualitygate/changeevent/QGChangeEventListenersImpl.java b/server/sonar-webserver-api/src/main/java/org/sonar/server/qualitygate/changeevent/QGChangeEventListenersImpl.java index 543a446e935..4cfca8d632f 100644 --- a/server/sonar-webserver-api/src/main/java/org/sonar/server/qualitygate/changeevent/QGChangeEventListenersImpl.java +++ b/server/sonar-webserver-api/src/main/java/org/sonar/server/qualitygate/changeevent/QGChangeEventListenersImpl.java @@ -19,14 +19,11 @@ */ package org.sonar.server.qualitygate.changeevent; +import com.google.common.collect.ImmutableSet; import com.google.common.collect.Multimap; import java.util.Collection; import java.util.List; -import java.util.Objects; import java.util.Set; -import javax.annotation.Nullable; -import org.sonar.api.issue.Issue; -import org.sonar.api.rules.RuleType; import org.sonar.api.utils.log.Logger; import org.sonar.api.utils.log.Loggers; import org.sonar.core.issue.DefaultIssue; @@ -46,127 +43,57 @@ import static org.sonar.core.util.stream.MoreCollectors.toSet; public class QGChangeEventListenersImpl implements QGChangeEventListeners { private static final Logger LOG = Loggers.get(QGChangeEventListenersImpl.class); - private final QGChangeEventListener[] listeners; + private final Set<QGChangeEventListener> listeners; - public QGChangeEventListenersImpl(@Nullable QGChangeEventListener[] listeners) { - this.listeners = listeners != null ? listeners : new QGChangeEventListener[0]; + public QGChangeEventListenersImpl(Set<QGChangeEventListener> listeners) { + this.listeners = listeners; } @Override - public void broadcastOnIssueChange(List<DefaultIssue> issues, Collection<QGChangeEvent> changeEvents) { - if (listeners.length == 0 || issues.isEmpty() || changeEvents.isEmpty()) { + public void broadcastOnIssueChange(List<DefaultIssue> issues, Collection<QGChangeEvent> changeEvents, boolean fromAlm) { + if (listeners.isEmpty() || issues.isEmpty() || changeEvents.isEmpty()) { return; } try { - Multimap<String, QGChangeEvent> eventsByBranchUuid = changeEvents.stream() - .collect(MoreCollectors.index(t -> t.getBranch().getUuid())); - Multimap<String, DefaultIssue> issueByBranchUuid = issues.stream() - .collect(MoreCollectors.index(DefaultIssue::projectUuid)); - - issueByBranchUuid.asMap().forEach((branchUuid, branchIssues) -> { - Collection<QGChangeEvent> qgChangeEvents = eventsByBranchUuid.get(branchUuid); - if (qgChangeEvents.isEmpty()) { - return; - } - Set<ChangedIssue> changedIssues = branchIssues.stream().map(ChangedIssueImpl::new).collect(toSet()); - for (QGChangeEvent changeEvent : qgChangeEvents) { - for (QGChangeEventListener listener : listeners) { - broadcastTo(changedIssues, changeEvent, listener); - } - } - }); + broadcastChangeEventsToBranches(issues, changeEvents, fromAlm); } catch (Error e) { LOG.warn(format("Broadcasting to listeners failed for %s events", changeEvents.size()), e); } } - private static void broadcastTo(Set<ChangedIssue> changedIssues, QGChangeEvent changeEvent, QGChangeEventListener listener) { - try { - LOG.trace("calling onChange() on listener {} for events {}...", listener.getClass().getName(), changeEvent); - listener.onIssueChanges(changeEvent, changedIssues); - } catch (Exception e) { - LOG.warn(format("onChange() call failed on listener %s for events %s", listener.getClass().getName(), changeEvent), e); - } - } - - static class ChangedIssueImpl implements ChangedIssue { - private final String key; - private final QGChangeEventListener.Status status; - private final RuleType type; - private final String severity; - - ChangedIssueImpl(DefaultIssue issue) { - this.key = issue.key(); - this.status = statusOf(issue); - this.type = issue.type(); - this.severity = issue.severity(); - } + private void broadcastChangeEventsToBranches(List<DefaultIssue> issues, Collection<QGChangeEvent> changeEvents, boolean fromAlm) { + Multimap<String, QGChangeEvent> eventsByBranchUuid = changeEvents.stream() + .collect(MoreCollectors.index(qgChangeEvent -> qgChangeEvent.getBranch().getUuid())); - static QGChangeEventListener.Status statusOf(DefaultIssue issue) { - switch (issue.status()) { - case Issue.STATUS_OPEN: - return QGChangeEventListener.Status.OPEN; - case Issue.STATUS_CONFIRMED: - return QGChangeEventListener.Status.CONFIRMED; - case Issue.STATUS_REOPENED: - return QGChangeEventListener.Status.REOPENED; - case Issue.STATUS_TO_REVIEW: - return QGChangeEventListener.Status.TO_REVIEW; - case Issue.STATUS_IN_REVIEW: - return QGChangeEventListener.Status.IN_REVIEW; - case Issue.STATUS_REVIEWED: - return QGChangeEventListener.Status.REVIEWED; - case Issue.STATUS_RESOLVED: - return statusOfResolved(issue); - default: - throw new IllegalStateException("Unexpected status: " + issue.status()); - } - } - - private static QGChangeEventListener.Status statusOfResolved(DefaultIssue issue) { - String resolution = issue.resolution(); - Objects.requireNonNull(resolution, "A resolved issue should have a resolution"); - switch (resolution) { - case Issue.RESOLUTION_FALSE_POSITIVE: - return QGChangeEventListener.Status.RESOLVED_FP; - case Issue.RESOLUTION_WONT_FIX: - return QGChangeEventListener.Status.RESOLVED_WF; - case Issue.RESOLUTION_FIXED: - return QGChangeEventListener.Status.RESOLVED_FIXED; - default: - throw new IllegalStateException("Unexpected resolution for a resolved issue: " + resolution); - } - } + Multimap<String, DefaultIssue> issueByBranchUuid = issues.stream() + .collect(MoreCollectors.index(DefaultIssue::projectUuid)); - @Override - public String getKey() { - return key; - } + issueByBranchUuid.asMap().forEach( + (branchUuid, branchIssues) -> broadcastChangeEventsToBranch(branchIssues, eventsByBranchUuid.get(branchUuid), fromAlm)); + } - @Override - public QGChangeEventListener.Status getStatus() { - return status; - } + private void broadcastChangeEventsToBranch(Collection<DefaultIssue> branchIssues, Collection<QGChangeEvent> branchQgChangeEvents, boolean fromAlm) { + Set<ChangedIssue> changedIssues = toChangedIssues(branchIssues, fromAlm); + branchQgChangeEvents.forEach(changeEvent -> broadcastChangeEventToListeners(changedIssues, changeEvent)); + } - @Override - public RuleType getType() { - return type; - } + private static ImmutableSet<ChangedIssue> toChangedIssues(Collection<DefaultIssue> defaultIssues, boolean fromAlm) { + return defaultIssues.stream() + .map(defaultIssue -> new ChangedIssueImpl(defaultIssue, fromAlm)) + .collect(toSet()); + } - @Override - public String getSeverity() { - return severity; - } + private void broadcastChangeEventToListeners(Set<ChangedIssue> changedIssues, QGChangeEvent changeEvent) { + listeners.forEach(listener -> broadcastChangeEventToListener(changedIssues, changeEvent, listener)); + } - @Override - public String toString() { - return "ChangedIssueImpl{" + - "key='" + key + '\'' + - ", status=" + status + - ", type=" + type + - ", severity=" + severity + - '}'; + private static void broadcastChangeEventToListener(Set<ChangedIssue> changedIssues, QGChangeEvent changeEvent, QGChangeEventListener listener) { + try { + LOG.trace("calling onChange() on listener {} for events {}...", listener.getClass().getName(), changeEvent); + listener.onIssueChanges(changeEvent, changedIssues); + } catch (Exception e) { + LOG.warn(format("onChange() call failed on listener %s for events %s", listener.getClass().getName(), changeEvent), e); } } diff --git a/server/sonar-webserver-api/src/test/java/org/sonar/server/qualitygate/changeevent/QGChangeEventListenersImplTest.java b/server/sonar-webserver-api/src/test/java/org/sonar/server/qualitygate/changeevent/QGChangeEventListenersImplTest.java index e5215ae5f31..44288f02548 100644 --- a/server/sonar-webserver-api/src/test/java/org/sonar/server/qualitygate/changeevent/QGChangeEventListenersImplTest.java +++ b/server/sonar-webserver-api/src/test/java/org/sonar/server/qualitygate/changeevent/QGChangeEventListenersImplTest.java @@ -24,6 +24,7 @@ import com.google.common.collect.ImmutableSet; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; +import java.util.LinkedHashSet; import java.util.List; import java.util.Random; import java.util.Set; @@ -43,7 +44,6 @@ import org.sonar.api.utils.log.LoggerLevel; import org.sonar.core.issue.DefaultIssue; import org.sonar.db.component.BranchDto; import org.sonar.server.qualitygate.changeevent.QGChangeEventListener.ChangedIssue; -import org.sonar.server.qualitygate.changeevent.QGChangeEventListenersImpl.ChangedIssueImpl; import static java.util.Collections.emptyList; import static java.util.Collections.emptySet; @@ -77,25 +77,25 @@ public class QGChangeEventListenersImplTest { private final InOrder inOrder = Mockito.inOrder(listener1, listener2, listener3); - private final QGChangeEventListenersImpl underTest = new QGChangeEventListenersImpl(new QGChangeEventListener[] {listener1, listener2, listener3}); + private final QGChangeEventListenersImpl underTest = new QGChangeEventListenersImpl(new LinkedHashSet<>(List.of(listener1, listener2, listener3))); @Test public void broadcastOnIssueChange_has_no_effect_when_issues_are_empty() { - underTest.broadcastOnIssueChange(emptyList(), singletonList(component1QGChangeEvent)); + underTest.broadcastOnIssueChange(emptyList(), singletonList(component1QGChangeEvent), false); verifyNoInteractions(listener1, listener2, listener3); } @Test public void broadcastOnIssueChange_has_no_effect_when_no_changeEvent() { - underTest.broadcastOnIssueChange(oneIssueOnComponent1, emptySet()); + underTest.broadcastOnIssueChange(oneIssueOnComponent1, emptySet(), false); verifyNoInteractions(listener1, listener2, listener3); } @Test public void broadcastOnIssueChange_passes_same_arguments_to_all_listeners_in_order_of_addition_to_constructor() { - underTest.broadcastOnIssueChange(oneIssueOnComponent1, singletonList(component1QGChangeEvent)); + underTest.broadcastOnIssueChange(oneIssueOnComponent1, singletonList(component1QGChangeEvent), false); ArgumentCaptor<Set<ChangedIssue>> changedIssuesCaptor = newSetCaptor(); inOrder.verify(listener1).onIssueChanges(same(component1QGChangeEvent), changedIssuesCaptor.capture()); @@ -112,7 +112,7 @@ public class QGChangeEventListenersImplTest { .when(failingListener) .onIssueChanges(any(), any()); - underTest.broadcastOnIssueChange(oneIssueOnComponent1, singletonList(component1QGChangeEvent)); + underTest.broadcastOnIssueChange(oneIssueOnComponent1, singletonList(component1QGChangeEvent), false); ArgumentCaptor<Set<ChangedIssue>> changedIssuesCaptor = newSetCaptor(); inOrder.verify(listener1).onIssueChanges(same(component1QGChangeEvent), changedIssuesCaptor.capture()); @@ -130,7 +130,7 @@ public class QGChangeEventListenersImplTest { .when(listener2) .onIssueChanges(any(), any()); - underTest.broadcastOnIssueChange(oneIssueOnComponent1, singletonList(component1QGChangeEvent)); + underTest.broadcastOnIssueChange(oneIssueOnComponent1, singletonList(component1QGChangeEvent), false); ArgumentCaptor<Set<ChangedIssue>> changedIssuesCaptor = newSetCaptor(); inOrder.verify(listener1).onIssueChanges(same(component1QGChangeEvent), changedIssuesCaptor.capture()); @@ -143,7 +143,7 @@ public class QGChangeEventListenersImplTest { @Test public void broadcastOnIssueChange_logs_each_listener_call_at_TRACE_level() { - underTest.broadcastOnIssueChange(oneIssueOnComponent1, singletonList(component1QGChangeEvent)); + underTest.broadcastOnIssueChange(oneIssueOnComponent1, singletonList(component1QGChangeEvent), false); assertThat(logTester.logs()).hasSize(3); List<String> traceLogs = logTester.logs(LoggerLevel.TRACE); @@ -156,9 +156,9 @@ public class QGChangeEventListenersImplTest { @Test public void broadcastOnIssueChange_passes_immutable_set_of_ChangedIssues() { - QGChangeEventListenersImpl underTest = new QGChangeEventListenersImpl(new QGChangeEventListener[] {listener1}); + QGChangeEventListenersImpl underTest = new QGChangeEventListenersImpl(Set.of(listener1)); - underTest.broadcastOnIssueChange(oneIssueOnComponent1, singletonList(component1QGChangeEvent)); + underTest.broadcastOnIssueChange(oneIssueOnComponent1, singletonList(component1QGChangeEvent), false); ArgumentCaptor<Set<ChangedIssue>> changedIssuesCaptor = newSetCaptor(); inOrder.verify(listener1).onIssueChanges(same(component1QGChangeEvent), changedIssuesCaptor.capture()); @@ -167,9 +167,9 @@ public class QGChangeEventListenersImplTest { @Test public void broadcastOnIssueChange_has_no_effect_when_no_listener() { - QGChangeEventListenersImpl underTest = new QGChangeEventListenersImpl(null); + QGChangeEventListenersImpl underTest = new QGChangeEventListenersImpl(Set.of()); - underTest.broadcastOnIssueChange(oneIssueOnComponent1, singletonList(component1QGChangeEvent)); + underTest.broadcastOnIssueChange(oneIssueOnComponent1, singletonList(component1QGChangeEvent), false); verifyNoInteractions(listener1, listener2, listener3); } @@ -213,7 +213,7 @@ public class QGChangeEventListenersImplTest { .flatMap(s -> s) .collect(Collectors.toList()); - underTest.broadcastOnIssueChange(changedIssues, randomizedList(qgChangeEvents)); + underTest.broadcastOnIssueChange(changedIssues, randomizedList(qgChangeEvents), false); listeners.forEach(listener -> { verifyListenerCalled(listener, component1QGChangeEvent, component1Issue); @@ -275,6 +275,41 @@ public class QGChangeEventListenersImplTest { } @Test + public void fromAlm_returns_false_by_default() { + DefaultIssue defaultIssue = new DefaultIssue(); + defaultIssue.setStatus(Issue.STATUS_OPEN); + + ChangedIssue changedIssue = new ChangedIssueImpl(defaultIssue); + + assertThat(changedIssue.fromAlm()).isFalse(); + } + + @Test + public void getSeverity_should_returns_default_issue_severity() { + DefaultIssue defaultIssue = new DefaultIssue(); + defaultIssue.setStatus(Issue.STATUS_OPEN); + defaultIssue.setSeverity("BLOCKER"); + + ChangedIssue changedIssue = new ChangedIssueImpl(defaultIssue); + + assertThat(changedIssue.getSeverity()).isEqualTo(defaultIssue.severity()); + } + + @Test + public void test_ChangedIssueImpl_toString() { + DefaultIssue defaultIssue = new DefaultIssue(); + defaultIssue.setStatus(Issue.STATUS_CONFIRMED); + defaultIssue.setKey("abc"); + defaultIssue.setType(RuleType.BUG); + defaultIssue.setSeverity("BLOCKER"); + String expected = "ChangedIssueImpl{key='abc', status=" + Issue.STATUS_CONFIRMED + ", type=" + RuleType.BUG + ", severity=BLOCKER, fromAlm=false}"; + + ChangedIssue changedIssue = new ChangedIssueImpl(defaultIssue); + + assertThat(changedIssue).hasToString(expected); + } + + @Test public void test_status_mapping() { assertThat(ChangedIssueImpl.statusOf(new DefaultIssue().setStatus(Issue.STATUS_OPEN))).isEqualTo(QGChangeEventListener.Status.OPEN); assertThat(ChangedIssueImpl.statusOf(new DefaultIssue().setStatus(Issue.STATUS_REOPENED))).isEqualTo(QGChangeEventListener.Status.REOPENED); @@ -345,12 +380,10 @@ public class QGChangeEventListenersImplTest { } private static String[] possibleResolutions(String status) { - switch (status) { - case Issue.STATUS_RESOLVED: - return new String[] {Issue.RESOLUTION_FALSE_POSITIVE, Issue.RESOLUTION_WONT_FIX}; - default: - return new String[0]; + if (Issue.STATUS_RESOLVED.equals(status)) { + return new String[]{Issue.RESOLUTION_FALSE_POSITIVE, Issue.RESOLUTION_WONT_FIX}; } + return new String[0]; } private static BranchDto newBranchDto(String uuid) { diff --git a/server/sonar-webserver-api/src/test/java/org/sonar/server/qualitygate/changeevent/QGChangeEventTest.java b/server/sonar-webserver-api/src/test/java/org/sonar/server/qualitygate/changeevent/QGChangeEventTest.java index a2f6d7c4238..8dafd4d1f1f 100644 --- a/server/sonar-webserver-api/src/test/java/org/sonar/server/qualitygate/changeevent/QGChangeEventTest.java +++ b/server/sonar-webserver-api/src/test/java/org/sonar/server/qualitygate/changeevent/QGChangeEventTest.java @@ -33,23 +33,24 @@ import org.sonar.db.project.ProjectDto; import org.sonar.server.qualitygate.EvaluatedQualityGate; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatCode; import static org.assertj.core.api.Assertions.assertThatThrownBy; public class QGChangeEventTest { - private ProjectDto project = new ProjectDto() + private final ProjectDto project = new ProjectDto() .setKey("foo") .setUuid("bar"); - private BranchDto branch = new BranchDto() + private final BranchDto branch = new BranchDto() .setBranchType(BranchType.BRANCH) .setUuid("bar") .setProjectUuid("doh") .setMergeBranchUuid("zop"); - private SnapshotDto analysis = new SnapshotDto() + private final SnapshotDto analysis = new SnapshotDto() .setUuid("pto") .setCreatedAt(8_999_999_765L); - private Configuration configuration = Mockito.mock(Configuration.class); - private Metric.Level previousStatus = Metric.Level.values()[new Random().nextInt(Metric.Level.values().length)]; + private final Configuration configuration = Mockito.mock(Configuration.class); + private final Metric.Level previousStatus = Metric.Level.values()[new Random().nextInt(Metric.Level.values().length)]; private Supplier<Optional<EvaluatedQualityGate>> supplier = Optional::empty; @Test @@ -82,7 +83,7 @@ public class QGChangeEventTest { @Test public void constructor_does_not_fail_with_NPE_if_previousStatus_is_null() { - new QGChangeEvent(project, branch, analysis, configuration, null, supplier); + assertThatCode(() -> new QGChangeEvent(project, branch, analysis, configuration, null, supplier)).doesNotThrowAnyException(); } @Test |