package org.mutabilitydetector.unittesting.internal;
/*
* #%L
* MutabilityDetector
* %%
* Copyright (C) 2008 - 2014 Graham Allan
* %%
* 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.
* #L%
*/
import static java.lang.System.getProperty;
import static java.util.Arrays.asList;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.allOf;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.fail;
import static org.mutabilitydetector.AnalysisResult.analysisResult;
import static org.mutabilitydetector.IsImmutable.IMMUTABLE;
import static org.mutabilitydetector.IsImmutable.NOT_IMMUTABLE;
import static org.mutabilitydetector.MutabilityReason.ESCAPED_THIS_REFERENCE;
import static org.mutabilitydetector.MutabilityReason.PUBLISHED_NON_FINAL_FIELD;
import static org.mutabilitydetector.MutableReasonDetail.newMutableReasonDetail;
import static org.mutabilitydetector.locations.CodeLocation.ClassLocation.from;
import static org.mutabilitydetector.locations.Dotted.dotted;
import static org.mutabilitydetector.unittesting.MutabilityMatchers.areImmutable;
import static org.mutabilitydetector.unittesting.matchers.IsImmutableMatcher.hasIsImmutableStatusOf;
import static org.mutabilitydetector.unittesting.matchers.reasons.WithAllowedReasonsMatcher.withNoAllowedReasons;
import java.util.Collection;
import org.junit.Before;
import org.junit.Test;
import org.mutabilitydetector.AnalysisResult;
import org.mutabilitydetector.IsImmutable;
import org.mutabilitydetector.MutableReasonDetail;
import org.mutabilitydetector.TestUtil;
import org.mutabilitydetector.locations.CodeLocation.ClassLocation;
import org.mutabilitydetector.locations.CodeLocation;
import org.mutabilitydetector.unittesting.MutabilityAssertionError;
public class AssertionReporterTest {
private AssertionReporter reporter;
private final String newline = getProperty("line.separator");
@Before
public void setUp() {
reporter = new AssertionReporter();
}
@Test
public void reporterDoesNotThrowAssertionErrorForImmutableResult() throws Exception {
AnalysisResult analysisResult = AnalysisResult.definitelyImmutable("a.b.c");
reporter.assertThat(analysisResult, withNoAllowedReasons(areImmutable()));
}
@Test(expected = MutabilityAssertionError.class)
public void reporterThrowsExceptionForMutableResult() {
AnalysisResult analysisResult = analysisResult("a.b.c", NOT_IMMUTABLE, unusedReasons());
reporter.assertThat(analysisResult, withNoAllowedReasons(areImmutable()));
}
@Test
public void thrownExceptionContainsHelpfulMessage() throws Exception {
CodeLocation<ClassLocation> codeLocation = ClassLocation.from(dotted("d.e.SimpleClassName"));
MutableReasonDetail reason = newMutableReasonDetail("a reason the class is mutable",
codeLocation,
PUBLISHED_NON_FINAL_FIELD);
AnalysisResult analysisResult = analysisResult("d.e.SimpleClassName", NOT_IMMUTABLE, reason);
try {
reporter.assertThat(analysisResult, withNoAllowedReasons(areImmutable()));
fail("expected exception");
} catch (MutabilityAssertionError e) {
String[] errorMessageLines = e.getMessage().split(newline);
assertThat(errorMessageLines[0], is(""));
assertThat(errorMessageLines[1], is("Expected: d.e.SimpleClassName to be " + IMMUTABLE));
assertThat(errorMessageLines[2], is(" but: d.e.SimpleClassName is actually " + NOT_IMMUTABLE));
assertThat(errorMessageLines[3], is(" Reasons:"));
assertThat(errorMessageLines[4], is(" a reason the class is mutable [Class: d.e.SimpleClassName]" ));
assertThat(errorMessageLines[5], is(" Allowed reasons:" ));
assertThat(errorMessageLines[6], is(" None." ));
}
}
@Test
public void expectedIsImmutableStatusDoesNotThrowException() throws Exception {
AnalysisResult analysisResult = analysisResult("g.h.i", IsImmutable.EFFECTIVELY_IMMUTABLE, unusedReasons());
reporter.assertThat(analysisResult, withNoAllowedReasons(hasIsImmutableStatusOf(IsImmutable.EFFECTIVELY_IMMUTABLE)));
}
@Test
public void performsAssertThatButWrapsExceptionInMutabilityAssertionErrorWithSameMessage() throws Exception {
MutableReasonDetail reasonDetail = newMutableReasonDetail("this message should appear",
from(dotted("a.b.c")),
ESCAPED_THIS_REFERENCE);
try {
reporter.assertThat(analysisResult("a.b.c", IsImmutable.NOT_IMMUTABLE, reasonDetail), withNoAllowedReasons(areImmutable()));
fail("expected exception");
} catch (MutabilityAssertionError expectedError) {
assertThat(expectedError.getMessage(), allOf(containsString("a.b.c to be IMMUTABLE" + newline),
containsString("a.b.c is actually NOT_IMMUTABLE" + newline),
containsString("this message should appear")));
}
}
private static Collection<MutableReasonDetail> unusedReasons() {
return TestUtil.unusedMutableReasonDetails();
}
}