Java tutorial
/* * Copyright 2017 Makoto Consulting Group, Inc. * * 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 com.makotojava.learn.junit5.math.solution; import static org.junit.jupiter.api.Assertions.assertAll; import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertIterableEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNotSame; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertSame; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTimeout; import static org.junit.jupiter.api.Assertions.assertTimeoutPreemptively; import static org.junit.jupiter.api.Assertions.assertTrue; import java.time.Duration; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import org.apache.commons.lang3.builder.ReflectionToStringBuilder; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Test; import com.makotojava.learn.junit5.math.YetAnotherUtility; /** * Tests the YetAnotherUtilityTest utility class. * * Demonstrates most of the methods and variants of the Jupiter * {@link org.junit.jupiter.api.Assertions Assertions} class. * * @author J Steven Perry * */ @DisplayName("Testing YetAnotherUtilityTest...") // @RunWith(JUnitPlatform.class) @Tag("solution") public class YetAnotherUtilityTest { /** * Generates a custom message using ReflectionToStringBuilder. * * @param expectedResults * The expected results * @param actualResults * The actual results * @return String - the message */ private String generateCustomMessage(Object expectedResults, Object actualResults) { return "Expected " + ReflectionToStringBuilder.toString(expectedResults) + " but instead got: " + ReflectionToStringBuilder.toString(actualResults); } /** * Utility method. Converts an array of primitives into a List * of the corresponding boxed type. * * @param actualResults * The array of primitives * * @return List - the resulting List of the primitives' corresponding boxed type */ private List<Long> primitiveArrayAsList(long[] actualResults) { // Convert this long[] to a List<Long>, which is Iterable List<Long> actualResultsIterable = new ArrayList<>(); for (long actualResult : actualResults) { actualResultsIterable.add(actualResult); } return actualResultsIterable; } /** * @Nested class. * Uses Assertions.assertArrayEquals(): * <ul> * <li>assertArrayEquals(expected, actual)</li> * <li>assertArrayEquals(expected, actual, String)</li> * <li>assertArrayEquals(expected, actual, Supplier<String>)</li> * </ul> * @author J Steven Perry * */ @Nested @DisplayName("When using assertArrayEquals...") public class AssertArrayEquals { @Test @DisplayName("computeFactors of 733 should return long[] = { 1, 733 }") void computeFactorsOfPrime() { long compoundInteger = 733; long[] expectedResults = { 1, 733 }; long[] actualResults = YetAnotherUtility.computeFactors(compoundInteger); // // Supplier<String> message - creates String lazily (only if assertion fails) assertArrayEquals(expectedResults, actualResults, () -> generateCustomMessage(expectedResults, actualResults)); } @Test @DisplayName("computeFactors of 1023 should return long[] = { 1, 3, 11, 31, 33, 93, 341, 1023 }") void computeFactorsOfNonPrime() { long compoundInteger = 1023; long[] expectedResults = { 1, 3, 11, 31, 33, 93, 341, 1023 }; long[] actualResults = YetAnotherUtility.computeFactors(compoundInteger); // // Supplier<String> message - creates String lazily (only if assertion fails) assertArrayEquals(expectedResults, actualResults, () -> generateCustomMessage(expectedResults, actualResults)); } } /** * @Nested class. * Uses Assertions.assertEquals() * <ul> * <li>assertEquals(expected, actual)</li> * <li>assertEquals(expected, actual, String)</li> * <li>assertEquals(expected, actual, Supplier<String>)</li> * </ul> * @author J Steven Perry * */ @Nested @DisplayName("When using assertEquals...") public class AssertEquals { @Test @DisplayName("computeFactors of 733 should return long[] = { 1, 733 }") void computeFactorsOfPrime() { long compoundInteger = 733; long[] expectedResults = { 1, 733 }; long[] actualResults = YetAnotherUtility.computeFactors(compoundInteger); assertEquals(expectedResults.length, actualResults.length); for (int aa = 0; aa < expectedResults.length; aa++) { // // Supplier<String> message - creates String lazily (only if assertion fails) { int index = aa; assertEquals(expectedResults[index], actualResults[index], () -> generateCustomMessage(expectedResults[index], actualResults[index])); } } } @Test @DisplayName("computeFactors of 1023 should return long[] = { 1, 3, 11, 31, 33, 93, 341, 1023 }") void computeFactorsOfNonPrime() { long compoundInteger = 1023; long[] expectedResults = { 1, 3, 11, 31, 33, 93, 341, 1023 }; long[] actualResults = YetAnotherUtility.computeFactors(compoundInteger); assertEquals(expectedResults.length, actualResults.length, generateCustomMessage(expectedResults.length, actualResults.length)); for (int aa = 0; aa < expectedResults.length; aa++) { // // Supplier<String> message - creates String lazily (only if assertion fails) { int index = aa; assertEquals(expectedResults[index], actualResults[index], () -> generateCustomMessage(expectedResults[index], actualResults[index])); } } } } /** * @Nested class * Uses Assertions.assertFalse(): * <ul> * <li>assertFalse(boolean)</li> * <li>assertFalse(boolean, String)</li> * <li>assertFalse(BooleanSupplier)</li> * <li>assertFalse(boolean, Supplier<String>)</li> * <li>assertFalse(BooleanSupplier, String)</li> * <li>assertFalse(BooleanSupplier, Supplier<String>)</li> * </ul> * @author J Steven Perry * */ @Nested @DisplayName("When using assertFalse...") public class AssertFalse { @Test @DisplayName("isPrime for 21 should return false") public void isPrime() { long candidateInteger = 21; // assertFalse(BooleanSupplier, Supplier<String>) assertFalse(() -> YetAnotherUtility.computeFactors(candidateInteger).length == 2, () -> candidateInteger + " was expected *not* to be prime."); } } /** * @Nested class. * Uses Assertions.assertIterableEquals(): * <ul> * <li>assertIterableEquals(Iterable<?>, Iterable<?>)</li> * <li>assertIterableEquals(Iterable<?>, Iterable<?>, String)</li> * <li>assertIterableEquals(Iterable<?>, Iterable<?>, Supplier<String>)</li> * </ul> * @author J Steven Perry * */ @Nested @DisplayName("When using assertIterableEquals...") public class AssertIterableEquals { @Test @DisplayName("computeFactors of 733 should return long[] = { 1, 733 }") void computeFactorsOfPrime() { long compoundInteger = 733; List<Long> expectedResultsIterable = Arrays.asList(new Long[] { 1L, 733L }); List<Long> actualResultsIterable = primitiveArrayAsList( YetAnotherUtility.computeFactors(compoundInteger)); // // Supplier<String> message - creates String lazily (only if assertion fails) assertIterableEquals(expectedResultsIterable, actualResultsIterable, () -> generateCustomMessage(expectedResultsIterable, actualResultsIterable)); } @Test @DisplayName("computeFactors of 1023 should return long[] = { 1, 3, 11, 31, 33, 93, 341, 1023 }") void computeFactorsOfNonPrime() { long compoundInteger = 1023; List<Long> expectedResultsIterable = Arrays .asList(new Long[] { 1L, 3L, 11L, 31L, 33L, 93L, 341L, 1023L }); List<Long> actualResultsIterable = primitiveArrayAsList( YetAnotherUtility.computeFactors(compoundInteger)); // // Supplier<String> message - creates String lazily (only if assertion fails) assertIterableEquals(expectedResultsIterable, actualResultsIterable, () -> generateCustomMessage(expectedResultsIterable, actualResultsIterable)); } } /** * @Nested class * Uses Assertions.assertNotNull(): * <ul> * <li>assertNotNull(Object)</li> * <li>assertNotNull(Object, String)</li> * <li>assertNotNull(Object, Supplier<String>)</li> * </ul> * @author J Steven Perry * */ @Nested @DisplayName("When using assertNotNull...") public class AssertNotNull { @Test @DisplayName("computeFactors of 733 should return a non-null array of factors") void computeFactors() { long candidateInteger = 733; // // Supplier<String> message - creates String lazily (only if assertion fails) assertNotNull(YetAnotherUtility.computeFactors(candidateInteger), () -> candidateInteger + " was expected to return a non-null array of factors"); } } /** * @Nested class * Uses Assertions.assertNotSame(): * <ul> * <li>assertNotSame(Object)</li> * <li>assertNotSame(Object, String)</li> * <li>assertNotSame(Object, Supplier<String>)</li> * </ul> * @author J Steven Perry * */ @Nested @DisplayName("When using assertNotSame") public class AssertNotSame { @Test @DisplayName("Different references to the same string are NOT the same object...") public void testAssertNotSame() { String expectedString = "this is a string of words".toUpperCase(); String actualString = "this is a string of words".toUpperCase(); // // The strings are .equals(), but different objects // // Supplier<String> message - creates String lazily (only if assertion fails) assertNotSame(expectedString, actualString, () -> "Expected strings to be the same objects"); } } /** * @Nested class * Uses Assertions.assertNull(): * <ul> * <li>assertNull(Object)</li> * <li>assertNull(Object, String)</li> * <li>assertNull(Object, Supplier<String>)</li> * </ul> * @author J Steven Perry * */ @Nested @DisplayName("When using assertNull...") public class AssertNull { @Test @DisplayName("computeFactors of 0 should return null") void computeFactors() { long candidateInteger = 0; // // Supplier<String> message - creates String lazily (only if assertion fails) assertNull(YetAnotherUtility.computeFactors(candidateInteger), () -> candidateInteger + " was expected to return null"); } } /** * @Nested class * Uses Assertions.assertSame(): * <ul> * <li>assertSame(Object)</li> * <li>assertSame(Object, String)</li> * <li>assertSame(Object, Supplier<String>)</li> * </ul> * @author J Steven Perry * */ @Nested @DisplayName("When using assertSame") public class AssertSame { @Test @DisplayName("Different references to the same string are the same object...") public void testAssertSame() { String expectedString = "This is a string of words,delimited by spaces, and, well, commas. Oh, and periods too."; String actualString = expectedString; // // The list that is returned is different // // Supplier<String> message - creates String lazily (only if assertion fails) assertSame(expectedString, actualString, () -> "Expected strings to be the same objects"); } @Test @DisplayName("Different references to the same string are the same object...") public void testAssertSameWithStringLiterals() { String expectedString = "This is a string of words"; String actualString = "This is a string of words"; // // The strings are .equals(), but different objects (or are they? no, no they're not) // // Supplier<String> message - creates String lazily (only if assertion fails) assertSame(expectedString, actualString, () -> "Expected strings to be the same objects"); } } /** * @Nested class * Uses Assertions.assertThrows(): * <ul> * <li>assertThrows(Class<T extends Throwable>, Executable)</li> * </ul> * @author J Steven Perry * */ @Nested @DisplayName("When using assertThrows...") public class AssertThrows { @Test @DisplayName("computeFactors with negative number throws IllegalArgumentException") void computeFactors() { // // If PrimeTime.isPrime() called with a negative number: IllegalArgumentException assertThrows(IllegalArgumentException.class, () -> YetAnotherUtility.computeFactors(-100L)); } } /** * @Nested class * Uses Assertions.assertTimeout(): * <ul> * <li>assertTimeout(Duration, Executable)</li> * <li>assertTimeout(Duration, Executable, String)</li> * <li>assertTimeout(Duration, Executable, Supplier<String>)</li> * <li>assertTimeout(Duration, ThrowingSupplier<T>)</li> * <li>assertTimeout(Duration, ThrowingSupplier<T>, String)</li> * <li>assertTimeout(Duration, ThrowingSupplier<T>, Supplier<String>)</li> * </ul> * @author J Steven Perry * */ @Nested @DisplayName("When using assertTimeout - exexutes in same Thread as Test...") public class AssertTimeout { @Test @DisplayName("computeFactors with 32767 * 10000 completes before 5000 ms") void computeFactors() { long compoundInteger = 32767L * 10000L; // Set Duration to 5000ms Duration timeout = Duration.ofMillis(5000); assertTimeout(timeout, () -> YetAnotherUtility.computeFactors(compoundInteger), () -> "Expected factorization of " + compoundInteger + " to complete before timeout of " + timeout.toMillis() + "ms"); } } /** * @Nested class * Uses Assertions.assertTimeoutPreemptively(): * <ul> * <li>assertTimeoutPreemptively(Duration, Executable)</li> * <li>assertTimeoutPreemptively(Duration, Executable, String)</li> * <li>assertTimeoutPreemptively(Duration, Executable, Supplier<String>)</li> * <li>assertTimeoutPreemptively(Duration, ThrowingSupplier<T>)</li> * <li>assertTimeoutPreemptively(Duration, ThrowingSupplier<T>, String)</li> * <li>assertTimeoutPreemptively(Duration, ThrowingSupplier<T>, Supplier<String>)</li> * </ul> * @author J Steven Perry * */ @Nested @DisplayName("When using assertTimeout - exexutes on different Thread from Test...") public class AssertTimeoutPreemptively { @Test @DisplayName("computeFactors with 32767 * 10000 completes before 5000 ms") void computeFactors() { long compoundInteger = 32767L * 10000L; // Set Duration to 5000ms Duration timeout = Duration.ofMillis(5000); // assertTimeoutPreemptively(timeout, () -> YetAnotherUtility.computeFactors(compoundInteger), () -> "Expected factorization of " + compoundInteger + " to complete before timeout of " + timeout.toMillis() + "ms"); } } /** * @Nested class * Uses Assertions.assertTrue(): * <ul> * <li>assertTrue(boolean)</li> * <li>assertTrue(boolean, String)</li> * <li>assertTrue(BooleanSupplier)</li> * <li>assertTrue(boolean, Supplier<String>)</li> * <li>assertTrue(BooleanSupplier, String)</li> * <li>assertTrue(BooleanSupplier, Supplier<String>)</li> * </ul> * @author J Steven Perry * */ @Nested @DisplayName("When using assertTrue with assertAll...") public class AssertTrue { @Test @DisplayName("isPrime for 23 should return true") public void isPrime() { long candidateInteger = 23; assertAll("Oh, look, it's a gaggle of Assertions", // AssertTrue(BooleanSupplier, String) () -> assertTrue(() -> YetAnotherUtility.computeFactors(candidateInteger).length == 2, candidateInteger + " was expected to be prime."), // AssertFalse(BooleanSupplier, Supplier<String>) () -> assertFalse(() -> YetAnotherUtility.computeFactors(candidateInteger).length > 2, () -> candidateInteger + " was expected to be prime.")); } } }