### Question:
DefaultRandomValues implements RandomValues { @Override public double randomDouble(final double lower, final double upper) { satisfies(lower <= upper, "the upper bound must be equal to or greater than the lower bound"); if (lower == upper) { return lower; } final double next = random.nextDouble(); return next * upper + (1.0 - next) * lower; } DefaultRandomValues(final Random random); @Override boolean randomBoolean(); @Override int randomInteger(final int lower, final int upper); @Override long randomLong(final long lower, final long upper); @Override double randomDouble(final double lower, final double upper); @Override double randomDouble(final double lower, final double upper, final int scale); @Override byte randomByte(final byte lower, final byte upper); @Override byte[] randomBytes(final int length); @Override short randomShort(final short lower, final short upper);  }### Answer:
@Test public void returnsRandomDoubleWithScale() { final double actualValue = randomValues.randomDouble(0.0, 100.0, 2); assertThat(scale(actualValue)) .describedAs("Scale should be 2dp, unless the second digit is zero (e.g 3.4056) when it will be 1dp (e.g 3.4)") .isBetween(1, 2); }
@Test public void returnsRandomDoubleWithZeroScale() { final double actualValue = randomValues.randomDouble(1.0, 1.0, 0); assertThat(actualValue).isEqualTo(1.0); }
@Test public void doubleScaledToZeroDpIsRoundedDownAndDoesNotExceedTheUpperBound() { final double nextDouble = 0.99999999; final RandomValues randomValues = new DefaultRandomValues(new Random() { @Override public double nextDouble() { return nextDouble; } }); final double actualValue = randomValues.randomDouble(0, 1.99, 0); assertThat(actualValue) .describedAs("When scaled the value 1.99 should be rounded down to 1.0 rather than up to 2.0 to avoid exceeding the upper bound") .isEqualTo(1.0); }
@Test public void doubleScaledToZeroDpIsRoundedUpWhenItWillNotExceedTheUpperBound() { final double nextDouble = 0.5; final RandomValues randomValues = new DefaultRandomValues(new Random() { @Override public double nextDouble() { return nextDouble; } }); final double actualValue = randomValues.randomDouble(0, 1.99, 0); assertThat(actualValue) .describedAs("When scaled the value 0.995 should be rounded up to 1 as it will not exceed the upper bound") .isEqualTo(1); }
@Test(expected = IllegalArgumentException.class) public void cannotGenerateDoubleWithNegativeScale() { randomValues.randomDouble(1.0, 1.0, -1); }
@Test(expected = IllegalArgumentException.class) public void cannotGenerateDoubleWhenLowerBoundIsGreaterThanUpperBound() { randomValues.randomDouble(1.0, 0.0); }
@Test(expected = IllegalArgumentException.class) public void cannotGenerateDoubleWhenLowerBoundIsGreaterThanUpperBoundForAnyGivenScale() { final int anyScale = new Random().nextInt(); randomValues.randomDouble(1.0, 0.0, anyScale); }
@Test public void returnsFixedDouble() { final double fixedValue = new Random().nextDouble(); final double actualValue = randomValues.randomDouble(fixedValue, fixedValue); assertThat(actualValue).isEqualTo(fixedValue); }
@Test public void returnsUpperBoundOfRandomDoubleWithScale() { final RandomValues randomValues = new DefaultRandomValues(new Random() { @Override public double nextDouble() { return 0.99999999999999; } }); final double actualValue = randomValues.randomDouble(0.0, 100.0, 2); assertThat(actualValue) .isEqualTo(100.00); }