From 50234dad1bf1694968a6078cf478418751e05bca Mon Sep 17 00:00:00 2001 From: hhimanshu Date: Wed, 20 May 2020 17:46:11 -0700 Subject: [PATCH 01/29] Added m04_01_testMortgageCalculatorExists, m04_02_testExistenceOfPrivateFields --- src/test/java/com/h2/Module04_Test.java | 95 +++++++++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 src/test/java/com/h2/Module04_Test.java diff --git a/src/test/java/com/h2/Module04_Test.java b/src/test/java/com/h2/Module04_Test.java new file mode 100644 index 000000000..947ffe39c --- /dev/null +++ b/src/test/java/com/h2/Module04_Test.java @@ -0,0 +1,95 @@ +package com.h2; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; +import org.junit.platform.commons.function.Try; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.InputStream; +import java.io.PrintStream; +import java.lang.reflect.Field; +import java.util.*; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.platform.commons.util.ReflectionUtils.isPrivate; +import static org.junit.platform.commons.util.ReflectionUtils.tryToLoadClass; + +public class Module04_Test { + private final String classToFind = "com.h2.MortgageCalculator"; + private final InputStream systemIn = System.in; + private final PrintStream systemOut = System.out; + + private ByteArrayInputStream testIn; + private ByteArrayOutputStream testOut; + + @BeforeEach + public void setUpOutput() { + testOut = new ByteArrayOutputStream(); + System.setOut(new PrintStream(testOut)); + } + + private void provideInput(String data) { + testIn = new ByteArrayInputStream(data.getBytes()); + System.setIn(testIn); + } + + private String getOutput() { + return testOut.toString(); + } + + @AfterEach + public void restoreSystemInputOutput() { + System.setIn(systemIn); + System.setOut(systemOut); + } + + private static Optional> getClass(final String className) { + Try> aClass = tryToLoadClass(className); + return aClass.toOptional(); + } + + public Optional> getMortgageClass() { + return getClass(classToFind); + } + + @Test + public void m04_01_testMortgageCalculatorExists() { + Optional> maybeClass = getMortgageClass(); + assertTrue(maybeClass.isPresent(), classToFind + " must be created."); + } + + @Test + public void m04_02_testExistenceOfPrivateFields() { + final Optional> maybeMortgageCalculator = getMortgageClass(); + assertTrue(maybeMortgageCalculator.isPresent(), classToFind + " must exist"); + final Class mortgageCalculator = maybeMortgageCalculator.get(); + final Map> expectedFieldsToClass = Map.of( + "loanAmount", long.class, + "termInYears", int.class, + "annualRate", float.class, + "monthlyPayment", double.class + ); + + final Field[] declaredFields = mortgageCalculator.getDeclaredFields(); + assertEquals(4, declaredFields.length, "4 fields (loanAmount, termInYears, annualRate, monthlyPayment) should be available in " + classToFind); + + + final Map> actualFieldsToClass = new HashMap<>(); + + for (final Field field : declaredFields) { + assertTrue(expectedFieldsToClass.containsKey(field.getName()), field.getName() + " is not a valid field name. It should be among (loanAmount, termInYears, annualRate, monthlyPayment)"); + assertTrue(isPrivate(field), field.getName() + " should be declared 'private'"); + actualFieldsToClass.put(field.getName(), field.getType()); + } + + expectedFieldsToClass.entrySet() + .forEach(e -> { + assertEquals(e.getValue(), actualFieldsToClass.get(e.getKey()), e.getKey() + " must be of type " + e.getValue()); + }); + + } +} From 1c6252fc0eb0fe2240ee57b02264a17d8200a17e Mon Sep 17 00:00:00 2001 From: hhimanshu Date: Wed, 20 May 2020 18:08:45 -0700 Subject: [PATCH 02/29] Added m4_03_testMortgageConstructorAndCorrectness --- src/test/java/com/h2/Module04_Test.java | 49 ++++++++++++++++++++++--- 1 file changed, 43 insertions(+), 6 deletions(-) diff --git a/src/test/java/com/h2/Module04_Test.java b/src/test/java/com/h2/Module04_Test.java index 947ffe39c..535165e6a 100644 --- a/src/test/java/com/h2/Module04_Test.java +++ b/src/test/java/com/h2/Module04_Test.java @@ -10,13 +10,15 @@ import java.io.ByteArrayOutputStream; import java.io.InputStream; import java.io.PrintStream; +import java.lang.reflect.Constructor; import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Parameter; import java.util.*; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.junit.platform.commons.util.ReflectionUtils.isPrivate; -import static org.junit.platform.commons.util.ReflectionUtils.tryToLoadClass; +import static org.junit.platform.commons.util.ReflectionUtils.*; public class Module04_Test { private final String classToFind = "com.h2.MortgageCalculator"; @@ -86,10 +88,45 @@ public void m04_02_testExistenceOfPrivateFields() { actualFieldsToClass.put(field.getName(), field.getType()); } - expectedFieldsToClass.entrySet() - .forEach(e -> { - assertEquals(e.getValue(), actualFieldsToClass.get(e.getKey()), e.getKey() + " must be of type " + e.getValue()); - }); + expectedFieldsToClass.forEach((key, value) -> assertEquals(value, actualFieldsToClass.get(key), key + " must be of type " + value)); + + } + + @Test + public void m4_03_testMortgageConstructorAndCorrectness() throws IllegalAccessException, InvocationTargetException, InstantiationException { + final Optional> maybeMortgageCalculator = getMortgageClass(); + assertTrue(maybeMortgageCalculator.isPresent(), classToFind + " must exist"); + final Class mortgageCalculator = maybeMortgageCalculator.get(); + final Constructor[] constructors = mortgageCalculator.getDeclaredConstructors(); + + assertEquals(1, constructors.length, classToFind + " should have 1 constructor"); + + final Constructor constructor = constructors[0]; + assertTrue(isPublic(constructor), "constructor must be declared 'public'"); + assertEquals(3, constructor.getParameterCount(), "Constructor should have 3 parameters"); + + Parameter[] parameters = constructor.getParameters(); + assertEquals(long.class, parameters[0].getType(), "Constructor's first parameter should be of type 'long'"); + assertEquals(int.class, parameters[1].getType(), "Constructor's second parameter should be of type 'int'"); + assertEquals(float.class, parameters[2].getType(), "Constructor's third parameter should be of type 'float'"); + + final long loanAmount = 100L; + final int termInYears = 20; + final float annualRate = 2.65f; + + Object instance = constructor.newInstance(loanAmount, termInYears, annualRate); + + final Field[] fields = mortgageCalculator.getDeclaredFields(); + for (Field field : fields) { + field.setAccessible(true); + if (field.getName().equals("loanAmount")) { + assertEquals(loanAmount, (long) field.get(instance), "loanAmount should have value of " + loanAmount); + } else if (field.getName().equals("termInYears")) { + assertEquals(termInYears, (int) field.get(instance), "termInYears should have value of " + termInYears); + } else if (field.getName().equals("annualRate")) { + assertEquals(annualRate, (float) field.get(instance), "annualRate should have value of " + annualRate); + } + } } } From 40e4cb6b93716b62939e8bc1e7972bea527c0c0b Mon Sep 17 00:00:00 2001 From: hhimanshu Date: Wed, 20 May 2020 18:09:14 -0700 Subject: [PATCH 03/29] Update m4_03_testMortgageConstructorAndCorrectness --- src/test/java/com/h2/Module04_Test.java | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/test/java/com/h2/Module04_Test.java b/src/test/java/com/h2/Module04_Test.java index 535165e6a..1320b1b27 100644 --- a/src/test/java/com/h2/Module04_Test.java +++ b/src/test/java/com/h2/Module04_Test.java @@ -119,12 +119,16 @@ public void m4_03_testMortgageConstructorAndCorrectness() throws IllegalAccessEx final Field[] fields = mortgageCalculator.getDeclaredFields(); for (Field field : fields) { field.setAccessible(true); - if (field.getName().equals("loanAmount")) { - assertEquals(loanAmount, (long) field.get(instance), "loanAmount should have value of " + loanAmount); - } else if (field.getName().equals("termInYears")) { - assertEquals(termInYears, (int) field.get(instance), "termInYears should have value of " + termInYears); - } else if (field.getName().equals("annualRate")) { - assertEquals(annualRate, (float) field.get(instance), "annualRate should have value of " + annualRate); + switch (field.getName()) { + case "loanAmount": + assertEquals(loanAmount, (long) field.get(instance), "loanAmount should have value of " + loanAmount); + break; + case "termInYears": + assertEquals(termInYears, (int) field.get(instance), "termInYears should have value of " + termInYears); + break; + case "annualRate": + assertEquals(annualRate, (float) field.get(instance), "annualRate should have value of " + annualRate); + break; } } From 1270a7b844f6ea30c5aa499af8e30cc01a6185b1 Mon Sep 17 00:00:00 2001 From: hhimanshu Date: Wed, 20 May 2020 18:24:27 -0700 Subject: [PATCH 04/29] Added m4_03_testExistenceOfNumberOfPayments --- src/test/java/com/h2/Module04_Test.java | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/src/test/java/com/h2/Module04_Test.java b/src/test/java/com/h2/Module04_Test.java index 1320b1b27..fead18b1e 100644 --- a/src/test/java/com/h2/Module04_Test.java +++ b/src/test/java/com/h2/Module04_Test.java @@ -10,11 +10,9 @@ import java.io.ByteArrayOutputStream; import java.io.InputStream; import java.io.PrintStream; -import java.lang.reflect.Constructor; -import java.lang.reflect.Field; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Parameter; +import java.lang.reflect.*; import java.util.*; +import java.util.stream.Collectors; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -133,4 +131,22 @@ public void m4_03_testMortgageConstructorAndCorrectness() throws IllegalAccessEx } } + + @Test + public void m4_03_testExistenceOfNumberOfPayments() { + final String methodName = "getNumberOfPayments"; + + final Optional> maybeMortgageCalculator = getMortgageClass(); + assertTrue(maybeMortgageCalculator.isPresent(), classToFind + " must exist"); + final Class mortgageCalculator = maybeMortgageCalculator.get(); + + final Method[] methods = mortgageCalculator.getDeclaredMethods(); + final List filteredMethod = Arrays.stream(methods).filter(method -> method.getName().equals(methodName)).collect(Collectors.toList()); + + assertEquals(1, filteredMethod.size(), classToFind + " should contain a method called '" + methodName + "'"); + + final Method sumOfCredits = filteredMethod.get(0); + assertTrue(isPrivate(sumOfCredits), methodName + " must be declared as 'private'"); + assertEquals(int.class, sumOfCredits.getReturnType(), methodName + " method must return a value of type 'int'"); + } } From c3838d46c0dd44b0682790cf21a01743257c9378 Mon Sep 17 00:00:00 2001 From: hhimanshu Date: Thu, 21 May 2020 16:06:53 -0700 Subject: [PATCH 05/29] Added m4_04_testNumberOfPaymentsCorrectness --- src/test/java/com/h2/Module04_Test.java | 37 ++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/src/test/java/com/h2/Module04_Test.java b/src/test/java/com/h2/Module04_Test.java index fead18b1e..0389b929a 100644 --- a/src/test/java/com/h2/Module04_Test.java +++ b/src/test/java/com/h2/Module04_Test.java @@ -2,7 +2,6 @@ import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.junit.platform.commons.function.Try; @@ -149,4 +148,40 @@ public void m4_03_testExistenceOfNumberOfPayments() { assertTrue(isPrivate(sumOfCredits), methodName + " must be declared as 'private'"); assertEquals(int.class, sumOfCredits.getReturnType(), methodName + " method must return a value of type 'int'"); } + + @Test + public void m4_04_testNumberOfPaymentsCorrectness() throws IllegalAccessException, InvocationTargetException, InstantiationException { + final Optional> maybeMortgageCalculator = getMortgageClass(); + assertTrue(maybeMortgageCalculator.isPresent(), classToFind + " must exist"); + final Class mortgageCalculator = maybeMortgageCalculator.get(); + final Constructor[] constructors = mortgageCalculator.getDeclaredConstructors(); + + assertEquals(1, constructors.length, classToFind + " should have 1 constructor"); + + final Constructor constructor = constructors[0]; + assertTrue(isPublic(constructor), "constructor must be declared 'public'"); + assertEquals(3, constructor.getParameterCount(), "Constructor should have 3 parameters"); + + Parameter[] parameters = constructor.getParameters(); + assertEquals(long.class, parameters[0].getType(), "Constructor's first parameter should be of type 'long'"); + assertEquals(int.class, parameters[1].getType(), "Constructor's second parameter should be of type 'int'"); + assertEquals(float.class, parameters[2].getType(), "Constructor's third parameter should be of type 'float'"); + + final long loanAmount = 100L; + final int termInYears = 20; + final float annualRate = 2.65f; + + Object instance = constructor.newInstance(loanAmount, termInYears, annualRate); + + final String methodName = "getNumberOfPayments"; + final List filteredMethod = Arrays.stream(mortgageCalculator.getDeclaredMethods()) + .filter(method -> method.getName().equals(methodName)) + .collect(Collectors.toList()); + + assertEquals(1, filteredMethod.size(), classToFind + " should contain a method called '" + methodName + "'"); + Method method = filteredMethod.get(0); + final float result = (int) invokeMethod(method, instance); + int expected = 12 * termInYears; + assertEquals(expected, result, methodName + " should return " + expected + " number of payments for termInYears of " + termInYears); + } } From 92341edaf6a63d689b5683cdcfc14ecf666bcdcf Mon Sep 17 00:00:00 2001 From: hhimanshu Date: Thu, 21 May 2020 16:14:16 -0700 Subject: [PATCH 06/29] Added m4_06_testExistenceOfMonthlyInterestRate --- src/test/java/com/h2/Module04_Test.java | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/src/test/java/com/h2/Module04_Test.java b/src/test/java/com/h2/Module04_Test.java index 0389b929a..a92ce7722 100644 --- a/src/test/java/com/h2/Module04_Test.java +++ b/src/test/java/com/h2/Module04_Test.java @@ -132,7 +132,7 @@ public void m4_03_testMortgageConstructorAndCorrectness() throws IllegalAccessEx } @Test - public void m4_03_testExistenceOfNumberOfPayments() { + public void m4_04_testExistenceOfNumberOfPayments() { final String methodName = "getNumberOfPayments"; final Optional> maybeMortgageCalculator = getMortgageClass(); @@ -150,7 +150,7 @@ public void m4_03_testExistenceOfNumberOfPayments() { } @Test - public void m4_04_testNumberOfPaymentsCorrectness() throws IllegalAccessException, InvocationTargetException, InstantiationException { + public void m4_05_testNumberOfPaymentsCorrectness() throws IllegalAccessException, InvocationTargetException, InstantiationException { final Optional> maybeMortgageCalculator = getMortgageClass(); assertTrue(maybeMortgageCalculator.isPresent(), classToFind + " must exist"); final Class mortgageCalculator = maybeMortgageCalculator.get(); @@ -184,4 +184,22 @@ public void m4_04_testNumberOfPaymentsCorrectness() throws IllegalAccessExceptio int expected = 12 * termInYears; assertEquals(expected, result, methodName + " should return " + expected + " number of payments for termInYears of " + termInYears); } + + @Test + public void m4_06_testExistenceOfMonthlyInterestRate() { + final String methodName = "getMonthlyInterestRate"; + + final Optional> maybeMortgageCalculator = getMortgageClass(); + assertTrue(maybeMortgageCalculator.isPresent(), classToFind + " must exist"); + final Class mortgageCalculator = maybeMortgageCalculator.get(); + + final Method[] methods = mortgageCalculator.getDeclaredMethods(); + final List filteredMethod = Arrays.stream(methods).filter(method -> method.getName().equals(methodName)).collect(Collectors.toList()); + + assertEquals(1, filteredMethod.size(), classToFind + " should contain a method called '" + methodName + "'"); + + final Method method = filteredMethod.get(0); + assertTrue(isPrivate(method), methodName + " must be declared as 'private'"); + assertEquals(float.class, method.getReturnType(), methodName + " method must return a value of type 'float'"); + } } From 177ba28c5473c6c98ad2cdfc4d4160dcef5dd672 Mon Sep 17 00:00:00 2001 From: hhimanshu Date: Thu, 21 May 2020 16:19:00 -0700 Subject: [PATCH 07/29] Added m4_07_testMonthlyInterestRateCorrectness --- src/test/java/com/h2/Module04_Test.java | 36 +++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/src/test/java/com/h2/Module04_Test.java b/src/test/java/com/h2/Module04_Test.java index a92ce7722..d6a773276 100644 --- a/src/test/java/com/h2/Module04_Test.java +++ b/src/test/java/com/h2/Module04_Test.java @@ -202,4 +202,40 @@ public void m4_06_testExistenceOfMonthlyInterestRate() { assertTrue(isPrivate(method), methodName + " must be declared as 'private'"); assertEquals(float.class, method.getReturnType(), methodName + " method must return a value of type 'float'"); } + + @Test + public void m4_07_testMonthlyInterestRateCorrectness() throws IllegalAccessException, InvocationTargetException, InstantiationException { + final Optional> maybeMortgageCalculator = getMortgageClass(); + assertTrue(maybeMortgageCalculator.isPresent(), classToFind + " must exist"); + final Class mortgageCalculator = maybeMortgageCalculator.get(); + final Constructor[] constructors = mortgageCalculator.getDeclaredConstructors(); + + assertEquals(1, constructors.length, classToFind + " should have 1 constructor"); + + final Constructor constructor = constructors[0]; + assertTrue(isPublic(constructor), "constructor must be declared 'public'"); + assertEquals(3, constructor.getParameterCount(), "Constructor should have 3 parameters"); + + Parameter[] parameters = constructor.getParameters(); + assertEquals(long.class, parameters[0].getType(), "Constructor's first parameter should be of type 'long'"); + assertEquals(int.class, parameters[1].getType(), "Constructor's second parameter should be of type 'int'"); + assertEquals(float.class, parameters[2].getType(), "Constructor's third parameter should be of type 'float'"); + + final long loanAmount = 100L; + final int termInYears = 20; + final float annualRate = 2.65f; + + Object instance = constructor.newInstance(loanAmount, termInYears, annualRate); + + final String methodName = "getMonthlyInterestRate"; + final List filteredMethod = Arrays.stream(mortgageCalculator.getDeclaredMethods()) + .filter(method -> method.getName().equals(methodName)) + .collect(Collectors.toList()); + + assertEquals(1, filteredMethod.size(), classToFind + " should contain a method called '" + methodName + "'"); + Method method = filteredMethod.get(0); + final float result = (float) invokeMethod(method, instance); + float expected = annualRate / 12; + assertEquals(expected, result, methodName + " should return " + expected + " as monthly interest rate for a annualRate of " + annualRate); + } } From 9a79ba1e99aab500f09581863fa07855d20949dc Mon Sep 17 00:00:00 2001 From: hhimanshu Date: Thu, 21 May 2020 16:32:40 -0700 Subject: [PATCH 08/29] Added m4_08_testExistenceOfCalculateMonthlyPayment --- src/test/java/com/h2/Module04_Test.java | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/test/java/com/h2/Module04_Test.java b/src/test/java/com/h2/Module04_Test.java index d6a773276..495e7340e 100644 --- a/src/test/java/com/h2/Module04_Test.java +++ b/src/test/java/com/h2/Module04_Test.java @@ -238,4 +238,22 @@ public void m4_07_testMonthlyInterestRateCorrectness() throws IllegalAccessExcep float expected = annualRate / 12; assertEquals(expected, result, methodName + " should return " + expected + " as monthly interest rate for a annualRate of " + annualRate); } + + @Test + public void m4_08_testExistenceOfCalculateMonthlyPayment() { + final String methodName = "calculateMonthlyPayment"; + + final Optional> maybeMortgageCalculator = getMortgageClass(); + assertTrue(maybeMortgageCalculator.isPresent(), classToFind + " must exist"); + final Class mortgageCalculator = maybeMortgageCalculator.get(); + + final Method[] methods = mortgageCalculator.getDeclaredMethods(); + final List filteredMethod = Arrays.stream(methods).filter(method -> method.getName().equals(methodName)).collect(Collectors.toList()); + + assertEquals(1, filteredMethod.size(), classToFind + " should contain a method called '" + methodName + "'"); + + final Method method = filteredMethod.get(0); + assertTrue(isPublic(method), methodName + " must be declared as 'public'"); + assertEquals(void.class, method.getReturnType(), methodName + " method must return a value of type 'void'"); + } } From 671784559ac2abdbb272180b527062597bc8abcc Mon Sep 17 00:00:00 2001 From: hhimanshu Date: Thu, 21 May 2020 17:27:17 -0700 Subject: [PATCH 09/29] Added m4_09_testCalculateMonthlyPaymentCorrectness --- src/test/java/com/h2/Module04_Test.java | 52 +++++++++++++++++++++++-- 1 file changed, 48 insertions(+), 4 deletions(-) diff --git a/src/test/java/com/h2/Module04_Test.java b/src/test/java/com/h2/Module04_Test.java index 495e7340e..1d974d2e0 100644 --- a/src/test/java/com/h2/Module04_Test.java +++ b/src/test/java/com/h2/Module04_Test.java @@ -13,8 +13,7 @@ import java.util.*; import java.util.stream.Collectors; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.*; import static org.junit.platform.commons.util.ReflectionUtils.*; public class Module04_Test { @@ -223,7 +222,7 @@ public void m4_07_testMonthlyInterestRateCorrectness() throws IllegalAccessExcep final long loanAmount = 100L; final int termInYears = 20; - final float annualRate = 2.65f; + final float annualRate = 3.74f; Object instance = constructor.newInstance(loanAmount, termInYears, annualRate); @@ -235,7 +234,7 @@ public void m4_07_testMonthlyInterestRateCorrectness() throws IllegalAccessExcep assertEquals(1, filteredMethod.size(), classToFind + " should contain a method called '" + methodName + "'"); Method method = filteredMethod.get(0); final float result = (float) invokeMethod(method, instance); - float expected = annualRate / 12; + float expected = (annualRate / 100) / 12; assertEquals(expected, result, methodName + " should return " + expected + " as monthly interest rate for a annualRate of " + annualRate); } @@ -256,4 +255,49 @@ public void m4_08_testExistenceOfCalculateMonthlyPayment() { assertTrue(isPublic(method), methodName + " must be declared as 'public'"); assertEquals(void.class, method.getReturnType(), methodName + " method must return a value of type 'void'"); } + + @Test + public void m4_09_testCalculateMonthlyPaymentCorrectness() throws IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchFieldException { + final Optional> maybeMortgageCalculator = getMortgageClass(); + assertTrue(maybeMortgageCalculator.isPresent(), classToFind + " must exist"); + final Class mortgageCalculator = maybeMortgageCalculator.get(); + final Constructor[] constructors = mortgageCalculator.getDeclaredConstructors(); + + assertEquals(1, constructors.length, classToFind + " should have 1 constructor"); + + final Constructor constructor = constructors[0]; + assertTrue(isPublic(constructor), "constructor must be declared 'public'"); + assertEquals(3, constructor.getParameterCount(), "Constructor should have 3 parameters"); + + Parameter[] parameters = constructor.getParameters(); + assertEquals(long.class, parameters[0].getType(), "Constructor's first parameter should be of type 'long'"); + assertEquals(int.class, parameters[1].getType(), "Constructor's second parameter should be of type 'int'"); + assertEquals(float.class, parameters[2].getType(), "Constructor's third parameter should be of type 'float'"); + + final long loanAmount = 264000; + final int termInYears = 30; + final float annualRate = 3.74f; + + Object instance = constructor.newInstance(loanAmount, termInYears, annualRate); + + final String methodName = "calculateMonthlyPayment"; + final List filteredMethod = Arrays.stream(mortgageCalculator.getDeclaredMethods()) + .filter(method -> method.getName().equals(methodName)) + .collect(Collectors.toList()); + + assertEquals(1, filteredMethod.size(), classToFind + " should contain a method called '" + methodName + "'"); + Method method = filteredMethod.get(0); + invokeMethod(method, instance); + double expected = 1221.1400903847025; + + String fieldName = "monthlyPayment"; + Field field = mortgageCalculator.getDeclaredField(fieldName); + field.setAccessible(true); + + double actual = field.getDouble(instance); + assertNotEquals(0.0, actual, fieldName + " should not be 0.0"); + + boolean areAlmostSame = Math.abs(expected - actual) < 0.001; + assertTrue(areAlmostSame, fieldName + " should be " + expected + " (or with a margin of +0.001), but was " + actual); + } } From a0defac683d51f50df4c38ddd8421cd087b273b9 Mon Sep 17 00:00:00 2001 From: hhimanshu Date: Thu, 21 May 2020 17:34:39 -0700 Subject: [PATCH 10/29] Added m3_10_testMainMethodExists --- src/test/java/com/h2/Module04_Test.java | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/test/java/com/h2/Module04_Test.java b/src/test/java/com/h2/Module04_Test.java index 1d974d2e0..c3c909818 100644 --- a/src/test/java/com/h2/Module04_Test.java +++ b/src/test/java/com/h2/Module04_Test.java @@ -300,4 +300,27 @@ public void m4_09_testCalculateMonthlyPaymentCorrectness() throws IllegalAccessE boolean areAlmostSame = Math.abs(expected - actual) < 0.001; assertTrue(areAlmostSame, fieldName + " should be " + expected + " (or with a margin of +0.001), but was " + actual); } + + @Test + public void m3_10_testMainMethodExists() { + final String methodName = "main"; + + final Optional> maybeMortgageCalculator = getMortgageClass(); + assertTrue(maybeMortgageCalculator.isPresent(), classToFind + " must exist"); + final Class mortgageCalculator = maybeMortgageCalculator.get(); + + final Method[] methods = mortgageCalculator.getDeclaredMethods(); + final List filteredMethod = Arrays.stream(methods).filter(method -> method.getName().equals(methodName)).collect(Collectors.toList()); + + assertEquals(1, filteredMethod.size(), classToFind + " should contain a method called '" + methodName + "'"); + + final Method method = filteredMethod.get(0); + assertTrue(isPublic(method), methodName + " must be declared as 'public'"); + assertTrue(isStatic(method), methodName + " must be declared as 'static'"); + assertEquals(void.class, method.getReturnType(), methodName + " method must return a value of type 'void'"); + + final Class[] parameterTypes = method.getParameterTypes(); + assertEquals(1, parameterTypes.length, methodName + " must accept 1 parameter."); + assertEquals(String[].class, parameterTypes[0], methodName + " must accept only 1 parameter of type 'String[]'"); + } } From faf0c80a5d554aee1db7f34e98cb69086e6795cb Mon Sep 17 00:00:00 2001 From: hhimanshu Date: Thu, 21 May 2020 18:04:15 -0700 Subject: [PATCH 11/29] Added m4_10_testExistenceOfToString --- src/test/java/com/h2/Module04_Test.java | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/src/test/java/com/h2/Module04_Test.java b/src/test/java/com/h2/Module04_Test.java index c3c909818..09aa557a6 100644 --- a/src/test/java/com/h2/Module04_Test.java +++ b/src/test/java/com/h2/Module04_Test.java @@ -9,6 +9,7 @@ import java.io.ByteArrayOutputStream; import java.io.InputStream; import java.io.PrintStream; +import java.lang.annotation.Annotation; import java.lang.reflect.*; import java.util.*; import java.util.stream.Collectors; @@ -302,7 +303,25 @@ public void m4_09_testCalculateMonthlyPaymentCorrectness() throws IllegalAccessE } @Test - public void m3_10_testMainMethodExists() { + public void m4_10_testExistenceOfToString() { + final String methodName = "toString"; + + final Optional> maybeMortgageCalculator = getMortgageClass(); + assertTrue(maybeMortgageCalculator.isPresent(), classToFind + " must exist"); + final Class mortgageCalculator = maybeMortgageCalculator.get(); + + final Method[] methods = mortgageCalculator.getDeclaredMethods(); + final List filteredMethod = Arrays.stream(methods).filter(method -> method.getName().equals(methodName)).collect(Collectors.toList()); + + assertEquals(1, filteredMethod.size(), classToFind + " should contain a method called '" + methodName + "'"); + + final Method method = filteredMethod.get(0); + assertTrue(isPublic(method), methodName + " must be declared as 'public'"); + assertEquals(String.class, method.getReturnType(), methodName + " method must return a value of type 'String'"); + } + + @Test + public void m3_xx_testMainMethodExists() { final String methodName = "main"; final Optional> maybeMortgageCalculator = getMortgageClass(); From dfb50a7bd1f5b0b10c253b98bc814a7839bf8a98 Mon Sep 17 00:00:00 2001 From: hhimanshu Date: Thu, 21 May 2020 18:20:12 -0700 Subject: [PATCH 12/29] Added m4_11_testToStringCorrectness --- src/test/java/com/h2/Module04_Test.java | 48 +++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/src/test/java/com/h2/Module04_Test.java b/src/test/java/com/h2/Module04_Test.java index 09aa557a6..5ee1919dc 100644 --- a/src/test/java/com/h2/Module04_Test.java +++ b/src/test/java/com/h2/Module04_Test.java @@ -320,6 +320,54 @@ public void m4_10_testExistenceOfToString() { assertEquals(String.class, method.getReturnType(), methodName + " method must return a value of type 'String'"); } + @Test + public void m4_11_testToStringCorrectness() throws IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchFieldException { + final Optional> maybeMortgageCalculator = getMortgageClass(); + assertTrue(maybeMortgageCalculator.isPresent(), classToFind + " must exist"); + final Class mortgageCalculator = maybeMortgageCalculator.get(); + final Constructor[] constructors = mortgageCalculator.getDeclaredConstructors(); + + assertEquals(1, constructors.length, classToFind + " should have 1 constructor"); + + final Constructor constructor = constructors[0]; + assertTrue(isPublic(constructor), "constructor must be declared 'public'"); + assertEquals(3, constructor.getParameterCount(), "Constructor should have 3 parameters"); + + Parameter[] parameters = constructor.getParameters(); + assertEquals(long.class, parameters[0].getType(), "Constructor's first parameter should be of type 'long'"); + assertEquals(int.class, parameters[1].getType(), "Constructor's second parameter should be of type 'int'"); + assertEquals(float.class, parameters[2].getType(), "Constructor's third parameter should be of type 'float'"); + + final long loanAmount = 264000; + final int termInYears = 30; + final float annualRate = 3.74f; + + Object instance = constructor.newInstance(loanAmount, termInYears, annualRate); + { + final String methodName = "calculateMonthlyPayment"; + final List filteredMethod = Arrays.stream(mortgageCalculator.getDeclaredMethods()) + .filter(method -> method.getName().equals(methodName)) + .collect(Collectors.toList()); + + assertEquals(1, filteredMethod.size(), classToFind + " should contain a method called '" + methodName + "'"); + Method method = filteredMethod.get(0); + invokeMethod(method, instance); + } + + { + final String methodName = "toString"; + final List filteredMethod = Arrays.stream(mortgageCalculator.getDeclaredMethods()) + .filter(method -> method.getName().equals(methodName)) + .collect(Collectors.toList()); + + assertEquals(1, filteredMethod.size(), classToFind + " should contain a method called '" + methodName + "'"); + Method method = filteredMethod.get(0); + final String result = (String) invokeMethod(method, instance); + final String expected = "monthlyPayment: 1221.14"; + assertEquals(expected, result, methodName + " should return " + expected); + } + } + @Test public void m3_xx_testMainMethodExists() { final String methodName = "main"; From cfe8bb03e26f3c45ba4e1356a1ef9b773d32f3f3 Mon Sep 17 00:00:00 2001 From: hhimanshu Date: Thu, 21 May 2020 18:29:24 -0700 Subject: [PATCH 13/29] Added m3_13_testMainMethodPrintsCorrectMortgageAmount --- src/test/java/com/h2/Module04_Test.java | 26 ++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/src/test/java/com/h2/Module04_Test.java b/src/test/java/com/h2/Module04_Test.java index 5ee1919dc..7f0a11a74 100644 --- a/src/test/java/com/h2/Module04_Test.java +++ b/src/test/java/com/h2/Module04_Test.java @@ -11,6 +11,7 @@ import java.io.PrintStream; import java.lang.annotation.Annotation; import java.lang.reflect.*; +import java.time.LocalDate; import java.util.*; import java.util.stream.Collectors; @@ -369,7 +370,7 @@ public void m4_11_testToStringCorrectness() throws IllegalAccessException, Invoc } @Test - public void m3_xx_testMainMethodExists() { + public void m3_12_testMainMethodExists() { final String methodName = "main"; final Optional> maybeMortgageCalculator = getMortgageClass(); @@ -390,4 +391,27 @@ public void m3_xx_testMainMethodExists() { assertEquals(1, parameterTypes.length, methodName + " must accept 1 parameter."); assertEquals(String[].class, parameterTypes[0], methodName + " must accept only 1 parameter of type 'String[]'"); } + + @Test + public void m3_13_testMainMethodPrintsCorrectMortgageAmount() throws InvocationTargetException, IllegalAccessException, NoSuchMethodException { + final String methodName = "main"; + + final Optional> maybeMortgageCalculator = getMortgageClass(); + assertTrue(maybeMortgageCalculator.isPresent(), classToFind + " must exist"); + final Class mortgageCalculator = maybeMortgageCalculator.get(); + + final Method[] methods = mortgageCalculator.getDeclaredMethods(); + + final List filteredMethod = Arrays.stream(methods).filter(method -> method.getName().equals(methodName)).collect(Collectors.toList()); + assertEquals(1, filteredMethod.size(), classToFind + " should contain a method called '" + methodName + "'"); + + final String loanAmount = "264000"; + final String termInYears = "30"; + final String annualRate = "3.74"; + + Method method = mortgageCalculator.getMethod("main", String[].class); + method.invoke(null, (Object) new String[]{loanAmount, termInYears, annualRate}); + + assertEquals("monthlyPayment: 1221.14" + "\n", testOut.toString()); + } } From d0df14da3dca4019b259d510581ff47270af6dbd Mon Sep 17 00:00:00 2001 From: hhimanshu Date: Thu, 21 May 2020 18:38:42 -0700 Subject: [PATCH 14/29] Added Updated test names --- src/test/java/com/h2/Module04_Test.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/java/com/h2/Module04_Test.java b/src/test/java/com/h2/Module04_Test.java index 7f0a11a74..f2ebbdc75 100644 --- a/src/test/java/com/h2/Module04_Test.java +++ b/src/test/java/com/h2/Module04_Test.java @@ -370,7 +370,7 @@ public void m4_11_testToStringCorrectness() throws IllegalAccessException, Invoc } @Test - public void m3_12_testMainMethodExists() { + public void m4_12_testMainMethodExists() { final String methodName = "main"; final Optional> maybeMortgageCalculator = getMortgageClass(); @@ -393,7 +393,7 @@ public void m3_12_testMainMethodExists() { } @Test - public void m3_13_testMainMethodPrintsCorrectMortgageAmount() throws InvocationTargetException, IllegalAccessException, NoSuchMethodException { + public void m4_13_testMainMethodPrintsCorrectMortgageAmount() throws InvocationTargetException, IllegalAccessException, NoSuchMethodException { final String methodName = "main"; final Optional> maybeMortgageCalculator = getMortgageClass(); From f638c0261043aaa648923f09f2a250b471761b8f Mon Sep 17 00:00:00 2001 From: hhimanshu Date: Fri, 22 May 2020 16:43:00 -0700 Subject: [PATCH 15/29] Added m5_01_assertFinanceClassExistence --- src/test/java/com/h2/Module05_Test.java | 26 +++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 src/test/java/com/h2/Module05_Test.java diff --git a/src/test/java/com/h2/Module05_Test.java b/src/test/java/com/h2/Module05_Test.java new file mode 100644 index 000000000..9973204f1 --- /dev/null +++ b/src/test/java/com/h2/Module05_Test.java @@ -0,0 +1,26 @@ +package com.h2; + +import org.junit.jupiter.api.Test; +import org.junit.platform.commons.function.Try; + +import java.util.Optional; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.platform.commons.util.ReflectionUtils.tryToLoadClass; + +public class Module05_Test { + private final String classToFind = "Finance"; + + public Optional> getAppClass() { + Try> aClass = tryToLoadClass(classToFind); + return aClass.toOptional(); + } + + @Test + public void m5_01_assertFinanceClassExistence() { + final Optional> maybeClass = getAppClass(); + assertTrue(maybeClass.isPresent(), classToFind + " should be present"); + assertEquals(classToFind, maybeClass.get().getCanonicalName()); + } +} From f462076e04dd7d0ca09a50bbb3115201bdc3b216 Mon Sep 17 00:00:00 2001 From: hhimanshu Date: Fri, 22 May 2020 17:01:46 -0700 Subject: [PATCH 16/29] Added m05_02_testCommandConstantFields --- src/test/java/com/h2/Module05_Test.java | 49 +++++++++++++++++++++++-- 1 file changed, 46 insertions(+), 3 deletions(-) diff --git a/src/test/java/com/h2/Module05_Test.java b/src/test/java/com/h2/Module05_Test.java index 9973204f1..86d9e1c76 100644 --- a/src/test/java/com/h2/Module05_Test.java +++ b/src/test/java/com/h2/Module05_Test.java @@ -3,24 +3,67 @@ import org.junit.jupiter.api.Test; import org.junit.platform.commons.function.Try; +import java.lang.reflect.Field; import java.util.Optional; +import java.util.Set; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.junit.platform.commons.util.ReflectionUtils.tryToLoadClass; +import static org.junit.platform.commons.util.ReflectionUtils.*; public class Module05_Test { private final String classToFind = "Finance"; - public Optional> getAppClass() { + public Optional> getFinanceClass() { Try> aClass = tryToLoadClass(classToFind); return aClass.toOptional(); } @Test public void m5_01_assertFinanceClassExistence() { - final Optional> maybeClass = getAppClass(); + final Optional> maybeClass = getFinanceClass(); assertTrue(maybeClass.isPresent(), classToFind + " should be present"); assertEquals(classToFind, maybeClass.get().getCanonicalName()); } + + @Test + public void m05_02_testCommandConstantFields() throws IllegalAccessException { + final Optional> maybeClass = getFinanceClass(); + assertTrue(maybeClass.isPresent(), classToFind + " should be present"); + assertEquals(classToFind, maybeClass.get().getCanonicalName()); + + final Class aClass = maybeClass.get(); + final Field[] fields = aClass.getDeclaredFields(); + + assertEquals(3, fields.length, classToFind + " should have 3 fields"); + + final Set fieldNames = Set.of("BEST_LOAN_RATES", "SAVINGS_CALCULATOR", "MORTGAGE_CALCULATOR"); + for(Field field: fields) { + String fieldName = field.getName(); + assertTrue(fieldNames.contains(fieldName), fieldName + " is not a valid field name. It should be among BEST_LOAN_RATES, SAVINGS_CALCULATOR, MORTGAGE_CALCULATOR"); + assertTrue(isPublic(field), fieldName + " must be declared 'public'"); + assertTrue(isStatic(field), fieldName + " must be declared 'static'"); + assertTrue(isFinal(field), fieldName + " must be declared 'final'"); + + switch (fieldName) { + case "BEST_LOAN_RATES": + assertEquals("bestLoanRates", field.get(null), "BEST_LOAN_RATES must have a value of 'bestLoanRates'"); + break; + case "SAVINGS_CALCULATOR": + assertEquals("savingsCalculator", field.get(null), "SAVINGS_CALCULATOR must have a value of 'savingsCalculator'"); + break; + case "MORTGAGE_CALCULATOR": + assertEquals("mortgageCalculator", field.get(null), "MORTGAGE_CALCULATOR must have a value of 'mortgageCalculator'"); + break; + } + } + + + /* + * 1. Existence of BEST_LOAN_RATES, SAVINGS_CALCULATOR, MORTGAGE_CALCULATOR + * 2. isPublic, isStatic, isFinal + * 3. Right values for each field + */ + } + } From 19575ce48cf74d45e27b9af992ed80da11d8eefd Mon Sep 17 00:00:00 2001 From: hhimanshu Date: Fri, 22 May 2020 17:25:57 -0700 Subject: [PATCH 17/29] Updated m05_02_testCommandConstantFields --- src/test/java/com/h2/Module05_Test.java | 53 +++++++++++++------------ 1 file changed, 28 insertions(+), 25 deletions(-) diff --git a/src/test/java/com/h2/Module05_Test.java b/src/test/java/com/h2/Module05_Test.java index 86d9e1c76..62c2df1eb 100644 --- a/src/test/java/com/h2/Module05_Test.java +++ b/src/test/java/com/h2/Module05_Test.java @@ -7,8 +7,7 @@ import java.util.Optional; import java.util.Set; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.*; import static org.junit.platform.commons.util.ReflectionUtils.*; public class Module05_Test { @@ -33,36 +32,40 @@ public void m05_02_testCommandConstantFields() throws IllegalAccessException { assertEquals(classToFind, maybeClass.get().getCanonicalName()); final Class aClass = maybeClass.get(); - final Field[] fields = aClass.getDeclaredFields(); - - assertEquals(3, fields.length, classToFind + " should have 3 fields"); final Set fieldNames = Set.of("BEST_LOAN_RATES", "SAVINGS_CALCULATOR", "MORTGAGE_CALCULATOR"); - for(Field field: fields) { - String fieldName = field.getName(); - assertTrue(fieldNames.contains(fieldName), fieldName + " is not a valid field name. It should be among BEST_LOAN_RATES, SAVINGS_CALCULATOR, MORTGAGE_CALCULATOR"); - assertTrue(isPublic(field), fieldName + " must be declared 'public'"); - assertTrue(isStatic(field), fieldName + " must be declared 'static'"); - assertTrue(isFinal(field), fieldName + " must be declared 'final'"); + for (String fieldName : fieldNames) { + try { + Field field = aClass.getDeclaredField(fieldName); + assertTrue(isPublic(field), fieldName + " must be declared 'public'"); + assertTrue(isStatic(field), fieldName + " must be declared 'static'"); + assertTrue(isFinal(field), fieldName + " must be declared 'final'"); + + switch (fieldName) { + case "BEST_LOAN_RATES": + assertEquals("bestLoanRates", field.get(null), "BEST_LOAN_RATES must have a value of 'bestLoanRates'"); + break; + case "SAVINGS_CALCULATOR": + assertEquals("savingsCalculator", field.get(null), "SAVINGS_CALCULATOR must have a value of 'savingsCalculator'"); + break; + case "MORTGAGE_CALCULATOR": + assertEquals("mortgageCalculator", field.get(null), "MORTGAGE_CALCULATOR must have a value of 'mortgageCalculator'"); + break; + } - switch (fieldName) { - case "BEST_LOAN_RATES": - assertEquals("bestLoanRates", field.get(null), "BEST_LOAN_RATES must have a value of 'bestLoanRates'"); - break; - case "SAVINGS_CALCULATOR": - assertEquals("savingsCalculator", field.get(null), "SAVINGS_CALCULATOR must have a value of 'savingsCalculator'"); - break; - case "MORTGAGE_CALCULATOR": - assertEquals("mortgageCalculator", field.get(null), "MORTGAGE_CALCULATOR must have a value of 'mortgageCalculator'"); - break; + } catch (NoSuchFieldException e) { + fail("Cannot find a field called " + fieldName); } } + } - + @Test + public void m5_03_testCommandsToUsage() { /* - * 1. Existence of BEST_LOAN_RATES, SAVINGS_CALCULATOR, MORTGAGE_CALCULATOR - * 2. isPublic, isStatic, isFinal - * 3. Right values for each field + * 1. Existence of field + * 2. isPublic, isFinal, isStatic, isMap (type) + * 3. Has 3 entries + * 4. Test all entries */ } From f22b7d5658bc485243e08b33d1816aa2ca0d050b Mon Sep 17 00:00:00 2001 From: hhimanshu Date: Fri, 22 May 2020 18:15:26 -0700 Subject: [PATCH 18/29] Added m5_03_testCommandsToUsage --- src/test/java/com/h2/Module05_Test.java | 32 ++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/src/test/java/com/h2/Module05_Test.java b/src/test/java/com/h2/Module05_Test.java index 62c2df1eb..4b45724f8 100644 --- a/src/test/java/com/h2/Module05_Test.java +++ b/src/test/java/com/h2/Module05_Test.java @@ -4,6 +4,7 @@ import org.junit.platform.commons.function.Try; import java.lang.reflect.Field; +import java.util.Map; import java.util.Optional; import java.util.Set; @@ -60,7 +61,36 @@ public void m05_02_testCommandConstantFields() throws IllegalAccessException { } @Test - public void m5_03_testCommandsToUsage() { + public void m5_03_testCommandsToUsage() throws IllegalAccessException { + final Optional> maybeClass = getFinanceClass(); + assertTrue(maybeClass.isPresent(), classToFind + " should be present"); + assertEquals(classToFind, maybeClass.get().getCanonicalName()); + + final Class aClass = maybeClass.get(); + + final String fieldName = "commandsToUsage"; + try { + Field field = aClass.getDeclaredField(fieldName); + field.setAccessible(true); + assertEquals(Map.class, field.getType(), fieldName + " must be of type 'Map'"); + + final Map expected = Map.of( + "bestLoanRates", "usage: bestLoanRates", + "savingsCalculator", "usage: savingsCalculator ", + "mortgageCalculator", "usage: mortgageCalculator " + ); + + @SuppressWarnings("unchecked") + Map commandsToUsage = (Map) field.get(null); + assertEquals(3, commandsToUsage.size(), fieldName + " should have 3 entries"); + expected.forEach((key, value) -> { + assertTrue(commandsToUsage.containsKey(key), key + " must be present in 'commandsToUsage'"); + assertEquals(value, commandsToUsage.get(key), key + " must have a value of - " + value); + }); + + } catch (NoSuchFieldException e) { + fail("Cannot find a field called " + fieldName); + } /* * 1. Existence of field * 2. isPublic, isFinal, isStatic, isMap (type) From e4eaa5e3740c52fb637048ff249805ff001394ff Mon Sep 17 00:00:00 2001 From: hhimanshu Date: Fri, 22 May 2020 18:37:45 -0700 Subject: [PATCH 19/29] Added m5_04_testExecuteCommandExistence --- src/test/java/com/h2/Module05_Test.java | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/src/test/java/com/h2/Module05_Test.java b/src/test/java/com/h2/Module05_Test.java index 4b45724f8..2d1b5bff8 100644 --- a/src/test/java/com/h2/Module05_Test.java +++ b/src/test/java/com/h2/Module05_Test.java @@ -4,6 +4,8 @@ import org.junit.platform.commons.function.Try; import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.lang.reflect.Parameter; import java.util.Map; import java.util.Optional; import java.util.Set; @@ -89,7 +91,7 @@ public void m5_03_testCommandsToUsage() throws IllegalAccessException { }); } catch (NoSuchFieldException e) { - fail("Cannot find a field called " + fieldName); + fail("Cannot find a field called " + fieldName + " in class " + classToFind); } /* * 1. Existence of field @@ -99,4 +101,23 @@ public void m5_03_testCommandsToUsage() throws IllegalAccessException { */ } + @Test + public void m5_04_testExecuteCommandExistence() { + final Optional> maybeClass = getFinanceClass(); + assertTrue(maybeClass.isPresent(), classToFind + " should be present"); + assertEquals(classToFind, maybeClass.get().getCanonicalName()); + + final Class aClass = maybeClass.get(); + final String methodName = "executeCommand"; + + try { + Method method = aClass.getDeclaredMethod(methodName, String.class, String[].class); + assertTrue(isPrivate(method), methodName + " must be declared 'private'"); + assertTrue(isStatic(method), methodName + " must be declared 'static'"); + assertEquals(void.class, method.getReturnType(), methodName + " must have a 'void' return type"); + + } catch (NoSuchMethodException e) { + fail("Can't find a method with name " + methodName + " in class " + classToFind + " with 2 parameters, first with type 'String', second with type 'String[]'"); + } + } } From ce44c9b9b432891f603999ee1cf84113376abc53 Mon Sep 17 00:00:00 2001 From: hhimanshu Date: Sat, 23 May 2020 11:58:25 -0700 Subject: [PATCH 20/29] Added m5_05_testExecuteCommandExistenceForCorrectness --- src/test/java/com/h2/Module04_Test.java | 2 - src/test/java/com/h2/Module05_Test.java | 104 +++++++++++++++++++++--- 2 files changed, 94 insertions(+), 12 deletions(-) diff --git a/src/test/java/com/h2/Module04_Test.java b/src/test/java/com/h2/Module04_Test.java index f2ebbdc75..0ad1deefc 100644 --- a/src/test/java/com/h2/Module04_Test.java +++ b/src/test/java/com/h2/Module04_Test.java @@ -9,9 +9,7 @@ import java.io.ByteArrayOutputStream; import java.io.InputStream; import java.io.PrintStream; -import java.lang.annotation.Annotation; import java.lang.reflect.*; -import java.time.LocalDate; import java.util.*; import java.util.stream.Collectors; diff --git a/src/test/java/com/h2/Module05_Test.java b/src/test/java/com/h2/Module05_Test.java index 2d1b5bff8..168e638fa 100644 --- a/src/test/java/com/h2/Module05_Test.java +++ b/src/test/java/com/h2/Module05_Test.java @@ -1,14 +1,18 @@ package com.h2; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.platform.commons.function.Try; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.InputStream; +import java.io.PrintStream; import java.lang.reflect.Field; import java.lang.reflect.Method; -import java.lang.reflect.Parameter; -import java.util.Map; -import java.util.Optional; -import java.util.Set; +import java.util.*; +import java.util.stream.Collectors; import static org.junit.jupiter.api.Assertions.*; import static org.junit.platform.commons.util.ReflectionUtils.*; @@ -16,6 +20,33 @@ public class Module05_Test { private final String classToFind = "Finance"; + private final InputStream systemIn = System.in; + private final PrintStream systemOut = System.out; + + private ByteArrayInputStream testIn; + private ByteArrayOutputStream testOut; + + @BeforeEach + public void setUpOutput() { + testOut = new ByteArrayOutputStream(); + System.setOut(new PrintStream(testOut)); + } + + private void provideInput(String data) { + testIn = new ByteArrayInputStream(data.getBytes()); + System.setIn(testIn); + } + + private String getOutput() { + return testOut.toString(); + } + + @AfterEach + public void restoreSystemInputOutput() { + System.setIn(systemIn); + System.setOut(systemOut); + } + public Optional> getFinanceClass() { Try> aClass = tryToLoadClass(classToFind); return aClass.toOptional(); @@ -93,12 +124,6 @@ public void m5_03_testCommandsToUsage() throws IllegalAccessException { } catch (NoSuchFieldException e) { fail("Cannot find a field called " + fieldName + " in class " + classToFind); } - /* - * 1. Existence of field - * 2. isPublic, isFinal, isStatic, isMap (type) - * 3. Has 3 entries - * 4. Test all entries - */ } @Test @@ -120,4 +145,63 @@ public void m5_04_testExecuteCommandExistence() { fail("Can't find a method with name " + methodName + " in class " + classToFind + " with 2 parameters, first with type 'String', second with type 'String[]'"); } } + + @Test + public void m5_05_testExecuteCommandExistenceForCorrectness() { + final String methodName = "executeCommand"; + + final Optional> maybeClass = getFinanceClass(); + assertTrue(maybeClass.isPresent(), classToFind + " must exist"); + final Class aClass = maybeClass.get(); + + final Method[] methods = aClass.getDeclaredMethods(); + final List filteredMethod = Arrays.stream(methods).filter(method -> method.getName().equals(methodName)).collect(Collectors.toList()); + assertEquals(1, filteredMethod.size(), classToFind + " should contain a method called '" + methodName + "'"); + + final Method method = filteredMethod.get(0); + { + final String credits = "10.0,20.0"; + final String debits = "5.0,20.0"; + + invokeMethod(method, null, "savingsCalculator", new String[]{credits, debits}); + + List consoleOutputs = Arrays.asList(testOut.toString().split("\n")); + + assertEquals(2, consoleOutputs.size(), "For case SAVINGS_CALCULATOR, " + methodName + " should print 2 statements on the console. One for 'Finding your net savings ...' and another one should be the output from the SavingsCalculator"); + assertEquals("Finding your net savings ...", consoleOutputs.get(0)); + assertTrue(consoleOutputs.get(1).startsWith("Net Savings = 5.0, remaining days in month = "), "For case SAVINGS_CALCULATOR, " + methodName + " should have printed an output similar to 'Net Savings = 51.0, remaining days in month = '"); + setUpOutput(); + } + { + final String loanAmount = "264000"; + final String termInYears = "30"; + final String annualRate = "3.74"; + invokeMethod(method, null, "mortgageCalculator", new String[]{loanAmount, termInYears, annualRate}); + + List consoleOutputs = Arrays.asList(testOut.toString().split("\n")); + + assertEquals(2, consoleOutputs.size(), "For case MORTGAGE_CALCULATOR, " + methodName + " should print 2 statements on the console. One for 'Finding your monthly payment ...' and another one should be the output from the MortgageCalculator"); + assertEquals("Finding your monthly payment ...", consoleOutputs.get(0)); + assertEquals("monthlyPayment: 1221.14", consoleOutputs.get(1)); + setUpOutput(); + } + { + final String name = "H2"; + final int loanTermInYears = 20; + final String testString = name + "\n" + loanTermInYears; + provideInput(testString); + + invokeMethod(method, null, "bestLoanRates", new String[]{}); + List consoleOutputs = Arrays.asList(testOut.toString().split("\n")); + + assertEquals(5, consoleOutputs.size(), "For case BEST_LOAN_RATES, There must be 4 statements on console - 1 for asking name, 1 for printing name back, 1 for asking loan term, 1 for printing no available rates for term (strictly in this order!)"); + + assertEquals("Finding best loan rates ...", consoleOutputs.get(0)); + assertEquals("Enter your name", consoleOutputs.get(1)); + assertEquals("Hello " + name, consoleOutputs.get(2)); + + assertEquals("Enter the loan term (in years)", consoleOutputs.get(3)); + assertEquals("No available rates for term: " + loanTermInYears + " years", consoleOutputs.get(4)); + } + } } From baa05be88ff6f8e09514949ec44a536911a9ae4b Mon Sep 17 00:00:00 2001 From: hhimanshu Date: Sat, 23 May 2020 12:57:27 -0700 Subject: [PATCH 21/29] Added m5_04_testValidateCommandArgumentsExistence, m5_05_testValidateCommandArgumentsCorrectness --- src/test/java/com/h2/Module05_Test.java | 70 ++++++++++++++++++++++++- 1 file changed, 68 insertions(+), 2 deletions(-) diff --git a/src/test/java/com/h2/Module05_Test.java b/src/test/java/com/h2/Module05_Test.java index 168e638fa..970bd211c 100644 --- a/src/test/java/com/h2/Module05_Test.java +++ b/src/test/java/com/h2/Module05_Test.java @@ -10,6 +10,7 @@ import java.io.InputStream; import java.io.PrintStream; import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.*; import java.util.stream.Collectors; @@ -127,7 +128,72 @@ public void m5_03_testCommandsToUsage() throws IllegalAccessException { } @Test - public void m5_04_testExecuteCommandExistence() { + public void m5_04_testValidateCommandArgumentsExistence() { + final Optional> maybeClass = getFinanceClass(); + assertTrue(maybeClass.isPresent(), classToFind + " should be present"); + assertEquals(classToFind, maybeClass.get().getCanonicalName()); + + final Class aClass = maybeClass.get(); + final String methodName = "validateCommandArguments"; + + try { + Method method = aClass.getDeclaredMethod(methodName, String[].class); + assertTrue(isPrivate(method), methodName + " must be declared 'private'"); + assertTrue(isStatic(method), methodName + " must be declared 'static'"); + assertEquals(boolean.class, method.getReturnType(), methodName + " must have a 'boolean' return type"); + + } catch (NoSuchMethodException e) { + fail("Can't find a method with name " + methodName + " in class " + classToFind + " with 1 parameter of type 'String[]'"); + } + } + + @Test + public void m5_05_testValidateCommandArgumentsCorrectness() throws InvocationTargetException, IllegalAccessException { + final Optional> maybeClass = getFinanceClass(); + assertTrue(maybeClass.isPresent(), classToFind + " should be present"); + assertEquals(classToFind, maybeClass.get().getCanonicalName()); + + final Class aClass = maybeClass.get(); + final String methodName = "validateCommandArguments"; + + try { + Method aMethod = aClass.getDeclaredMethod(methodName, String[].class); + aMethod.setAccessible(true); + { + boolean actual = (boolean) aMethod.invoke(null, (Object) new String[]{"bestLoanRates"}); + assertTrue(actual, methodName + " should have returned 'true' for bestLoanRates with no additional arguments"); + } + { + boolean actual = (boolean) aMethod.invoke(null, (Object) new String[]{"bestLoanRates", "1"}); + assertFalse(actual, methodName + " should have returned 'false' for bestLoanRates with 1 additional argument"); + } + { + boolean actual = (boolean) aMethod.invoke(null, (Object) new String[]{"savingsCalculator", "1"}); + assertFalse(actual, methodName + " should have returned 'false' for savingsCalculator with 1 additional argument"); + } + { + boolean actual = (boolean) aMethod.invoke(null, (Object) new String[]{"savingsCalculator", "1", "2"}); + assertTrue(actual, methodName + " should have returned 'true' for savingsCalculator with 2 additional arguments"); + } + { + boolean actual = (boolean) aMethod.invoke(null, (Object) new String[]{"mortgageCalculator", "1", "2"}); + assertFalse(actual, methodName + " should have returned 'false' for mortgageCalculator with 2 additional arguments"); + } + { + boolean actual = (boolean) aMethod.invoke(null, (Object) new String[]{"mortgageCalculator", "1", "2", "3"}); + assertTrue(actual, methodName + " should have returned 'true' for mortgageCalculator with 3 additional arguments"); + } + { + boolean actual = (boolean) aMethod.invoke(null, (Object) new String[]{"heightCalculator"}); + assertFalse(actual, methodName + " should have returned 'false' for unknown app name 'heightCalculator'"); + } + } catch (NoSuchMethodException e) { + fail("Can't find a method with name " + methodName + " in class " + classToFind + " with 1 parameter of type 'String[]'"); + } + } + + @Test + public void m5_06_testExecuteCommandExistence() { final Optional> maybeClass = getFinanceClass(); assertTrue(maybeClass.isPresent(), classToFind + " should be present"); assertEquals(classToFind, maybeClass.get().getCanonicalName()); @@ -147,7 +213,7 @@ public void m5_04_testExecuteCommandExistence() { } @Test - public void m5_05_testExecuteCommandExistenceForCorrectness() { + public void m5_07_testExecuteCommandExistenceForCorrectness() { final String methodName = "executeCommand"; final Optional> maybeClass = getFinanceClass(); From 4c79e53dcc2df4cac57de11d9641e9a5829120c4 Mon Sep 17 00:00:00 2001 From: hhimanshu Date: Sat, 23 May 2020 13:32:13 -0700 Subject: [PATCH 22/29] Added m5_08_testFinanceMainMethodExists, m5_09_testFinanceMainMethodWorksCorrectly --- src/test/java/com/h2/Module05_Test.java | 66 +++++++++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/src/test/java/com/h2/Module05_Test.java b/src/test/java/com/h2/Module05_Test.java index 970bd211c..2375bccc2 100644 --- a/src/test/java/com/h2/Module05_Test.java +++ b/src/test/java/com/h2/Module05_Test.java @@ -270,4 +270,70 @@ public void m5_07_testExecuteCommandExistenceForCorrectness() { assertEquals("No available rates for term: " + loanTermInYears + " years", consoleOutputs.get(4)); } } + + @Test + public void m5_08_testFinanceMainMethodExists() { + final String methodName = "main"; + + final Optional> maybeClass = getFinanceClass(); + assertTrue(maybeClass.isPresent(), classToFind + " must exist"); + final Class aClass = maybeClass.get(); + + final Method[] methods = aClass.getDeclaredMethods(); + final List filteredMethod = Arrays.stream(methods).filter(method -> method.getName().equals(methodName)).collect(Collectors.toList()); + + assertEquals(1, filteredMethod.size(), classToFind + " should contain a method called '" + methodName + "'"); + + final Method method = filteredMethod.get(0); + assertTrue(isPublic(method), methodName + " must be declared as 'public'"); + assertTrue(isStatic(method), methodName + " must be declared as 'static'"); + assertEquals(void.class, method.getReturnType(), methodName + " method must return a value of type 'void'"); + + final Class[] parameterTypes = method.getParameterTypes(); + assertEquals(1, parameterTypes.length, methodName + " must accept 1 parameter."); + assertEquals(String[].class, parameterTypes[0], methodName + " must accept only 1 parameter of type 'String[]'"); + } + @Test + public void m5_09_testFinanceMainMethodWorksCorrectly() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { + final String methodName = "main"; + + final Optional> maybeClass = getFinanceClass(); + assertTrue(maybeClass.isPresent(), classToFind + " must exist"); + final Class aClass = maybeClass.get(); + + final Method[] methods = aClass.getDeclaredMethods(); + final List filteredMethod = Arrays.stream(methods).filter(method -> method.getName().equals(methodName)).collect(Collectors.toList()); + assertEquals(1, filteredMethod.size(), classToFind + " should contain a method called '" + methodName + "'"); + + + + Method method = aClass.getMethod("main", String[].class); + { + String command = "LaunchRocketToMoon"; + method.invoke(null, (Object) new String[]{command}); + assertEquals(command + ": command not found" + "\n", testOut.toString()); + } + { + setUpOutput(); + final String loanAmount = "264000"; + final String termInYears = "30"; + method.invoke(null, (Object) new String[]{"mortgageCalculator", loanAmount, termInYears}); + assertEquals("usage: mortgageCalculator " + "\n", testOut.toString()); + } + { + setUpOutput(); + final String loanAmount = "264000"; + final String termInYears = "30"; + final String annualRate = "3.74"; + + method.invoke(null, (Object) new String[]{"mortgageCalculator", loanAmount, termInYears, annualRate}); + //invokeMethod(method, null, "mortgageCalculator", new String[]{loanAmount, termInYears, annualRate}); + + List consoleOutputs = Arrays.asList(testOut.toString().split("\n")); + + assertEquals(2, consoleOutputs.size(), "For case MORTGAGE_CALCULATOR, " + methodName + " should print 2 statements on the console. One for 'Finding your monthly payment ...' and another one should be the output from the MortgageCalculator"); + assertEquals("Finding your monthly payment ...", consoleOutputs.get(0)); + assertEquals("monthlyPayment: 1221.14", consoleOutputs.get(1)); + } + } } From 6fe71ed2c29f6a88c974037b5adcfb45577a787b Mon Sep 17 00:00:00 2001 From: hhimanshu Date: Sat, 23 May 2020 13:32:48 -0700 Subject: [PATCH 23/29] Updated m5_09_testFinanceMainMethodWorksCorrectly --- src/test/java/com/h2/Module05_Test.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/test/java/com/h2/Module05_Test.java b/src/test/java/com/h2/Module05_Test.java index 2375bccc2..899f7aa60 100644 --- a/src/test/java/com/h2/Module05_Test.java +++ b/src/test/java/com/h2/Module05_Test.java @@ -327,8 +327,6 @@ public void m5_09_testFinanceMainMethodWorksCorrectly() throws NoSuchMethodExcep final String annualRate = "3.74"; method.invoke(null, (Object) new String[]{"mortgageCalculator", loanAmount, termInYears, annualRate}); - //invokeMethod(method, null, "mortgageCalculator", new String[]{loanAmount, termInYears, annualRate}); - List consoleOutputs = Arrays.asList(testOut.toString().split("\n")); assertEquals(2, consoleOutputs.size(), "For case MORTGAGE_CALCULATOR, " + methodName + " should print 2 statements on the console. One for 'Finding your monthly payment ...' and another one should be the output from the MortgageCalculator"); From ad83ad53c6afa0c20b034b0e2a50757d009f899b Mon Sep 17 00:00:00 2001 From: hhimanshu Date: Sat, 23 May 2020 16:50:02 -0700 Subject: [PATCH 24/29] Added m6_01_assertFinanceClassExistence --- src/test/java/com/h2/Module06_Test.java | 26 +++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 src/test/java/com/h2/Module06_Test.java diff --git a/src/test/java/com/h2/Module06_Test.java b/src/test/java/com/h2/Module06_Test.java new file mode 100644 index 000000000..eb1377f01 --- /dev/null +++ b/src/test/java/com/h2/Module06_Test.java @@ -0,0 +1,26 @@ +package com.h2; + +import org.junit.jupiter.api.Test; +import org.junit.platform.commons.function.Try; + +import java.util.Optional; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.platform.commons.util.ReflectionUtils.tryToLoadClass; + +public class Module06_Test { + private final String classToFind = "com.h2.Utilities"; + + public Optional> getUtilitiesClass() { + Try> aClass = tryToLoadClass(classToFind); + return aClass.toOptional(); + } + + @Test + public void m6_01_assertFinanceClassExistence() { + final Optional> maybeClass = getUtilitiesClass(); + assertTrue(maybeClass.isPresent(), classToFind + " should be present"); + assertEquals(classToFind, maybeClass.get().getCanonicalName()); + } +} From 8d71784169acf0df424dc11b5abd9c44b8f3a7e9 Mon Sep 17 00:00:00 2001 From: hhimanshu Date: Sat, 23 May 2020 17:00:50 -0700 Subject: [PATCH 25/29] Added m6_02_testGetLongValueExistence --- src/test/java/com/h2/Module06_Test.java | 26 ++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/src/test/java/com/h2/Module06_Test.java b/src/test/java/com/h2/Module06_Test.java index eb1377f01..0b510b81a 100644 --- a/src/test/java/com/h2/Module06_Test.java +++ b/src/test/java/com/h2/Module06_Test.java @@ -3,11 +3,11 @@ import org.junit.jupiter.api.Test; import org.junit.platform.commons.function.Try; +import java.lang.reflect.Method; import java.util.Optional; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.junit.platform.commons.util.ReflectionUtils.tryToLoadClass; +import static org.junit.jupiter.api.Assertions.*; +import static org.junit.platform.commons.util.ReflectionUtils.*; public class Module06_Test { private final String classToFind = "com.h2.Utilities"; @@ -23,4 +23,24 @@ public void m6_01_assertFinanceClassExistence() { assertTrue(maybeClass.isPresent(), classToFind + " should be present"); assertEquals(classToFind, maybeClass.get().getCanonicalName()); } + + @Test + public void m6_02_testGetLongValueExistence() { + final String methodName = "getLongValue"; + final Optional> maybeClass = getUtilitiesClass(); + assertTrue(maybeClass.isPresent(), classToFind + " should be present"); + assertEquals(classToFind, maybeClass.get().getCanonicalName()); + + final Class aClass = maybeClass.get(); + + try { + Method method = aClass.getDeclaredMethod(methodName, String.class); + assertTrue(isPublic(method), methodName + " must be declared 'public'"); + assertTrue(isStatic(method), methodName + " must be declared 'static'"); + assertEquals(long.class, method.getReturnType(), methodName + " must have a 'long' return type"); + + } catch (NoSuchMethodException e) { + fail("Can't find a method with name " + methodName + " in class " + classToFind + " with 1 parameter of type 'String'"); + } + } } From 66d21bb5dbaed83eaf8c558ad73a0cf3cf5810c4 Mon Sep 17 00:00:00 2001 From: hhimanshu Date: Sat, 23 May 2020 17:38:09 -0700 Subject: [PATCH 26/29] Added m6_03_testGetLongValueCorrectness --- src/test/java/com/h2/Module06_Test.java | 30 +++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/src/test/java/com/h2/Module06_Test.java b/src/test/java/com/h2/Module06_Test.java index 0b510b81a..0d2686a90 100644 --- a/src/test/java/com/h2/Module06_Test.java +++ b/src/test/java/com/h2/Module06_Test.java @@ -3,6 +3,7 @@ import org.junit.jupiter.api.Test; import org.junit.platform.commons.function.Try; +import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.Optional; @@ -12,6 +13,7 @@ public class Module06_Test { private final String classToFind = "com.h2.Utilities"; + public Optional> getUtilitiesClass() { Try> aClass = tryToLoadClass(classToFind); return aClass.toOptional(); @@ -43,4 +45,32 @@ public void m6_02_testGetLongValueExistence() { fail("Can't find a method with name " + methodName + " in class " + classToFind + " with 1 parameter of type 'String'"); } } + + @Test + public void m6_03_testGetLongValueCorrectness() throws IllegalAccessException, InvocationTargetException { + final String methodName = "getLongValue"; + final Optional> maybeClass = getUtilitiesClass(); + assertTrue(maybeClass.isPresent(), classToFind + " should be present"); + assertEquals(classToFind, maybeClass.get().getCanonicalName()); + + final Class aClass = maybeClass.get(); + try { + Method method = aClass.getMethod(methodName, String.class); + { + long result = (long) method.invoke(null, "123"); + assertEquals(123L, result, methodName + " should convert '123' into '123L'"); + } + { + String input = "1.22"; + final InvocationTargetException exception = assertThrows(InvocationTargetException.class, () -> method.invoke(null, input)); + Throwable targetException = exception.getTargetException(); + assertEquals(IllegalArgumentException.class, targetException.getClass(), methodName + " should have thrown an instance of 'IllegalArgumentException'"); + assertEquals(input + " cannot be converted into a 'long' value. Exiting program.", targetException.getMessage()); + } + + } catch (NoSuchMethodException e) { + fail("Can't find a method with name " + methodName + " in class " + classToFind + " with 1 parameter of type 'String'"); + } + + } } From f3e065a2838bf4a22845af8daa5d3dd44e65a75e Mon Sep 17 00:00:00 2001 From: hhimanshu Date: Sat, 23 May 2020 17:52:33 -0700 Subject: [PATCH 27/29] Added m6_04_testGetIntValueExistenceAndCorrectness --- src/test/java/com/h2/Module06_Test.java | 30 ++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/src/test/java/com/h2/Module06_Test.java b/src/test/java/com/h2/Module06_Test.java index 0d2686a90..af67a2a5b 100644 --- a/src/test/java/com/h2/Module06_Test.java +++ b/src/test/java/com/h2/Module06_Test.java @@ -67,10 +67,38 @@ public void m6_03_testGetLongValueCorrectness() throws IllegalAccessException, I assertEquals(IllegalArgumentException.class, targetException.getClass(), methodName + " should have thrown an instance of 'IllegalArgumentException'"); assertEquals(input + " cannot be converted into a 'long' value. Exiting program.", targetException.getMessage()); } - } catch (NoSuchMethodException e) { fail("Can't find a method with name " + methodName + " in class " + classToFind + " with 1 parameter of type 'String'"); } + } + + @Test + public void m6_04_testGetIntValueExistenceAndCorrectness() throws IllegalAccessException, InvocationTargetException { + final String methodName = "getIntValue"; + final Optional> maybeClass = getUtilitiesClass(); + assertTrue(maybeClass.isPresent(), classToFind + " should be present"); + assertEquals(classToFind, maybeClass.get().getCanonicalName()); + final Class aClass = maybeClass.get(); + try { + Method method = aClass.getMethod(methodName, String.class); + assertTrue(isPublic(method), methodName + " must be declared 'public'"); + assertTrue(isStatic(method), methodName + " must be declared 'static'"); + assertEquals(int.class, method.getReturnType(), methodName + " must have a 'int' return type"); + + { + int result = (int) method.invoke(null, "100"); + assertEquals(100, result, methodName + " should convert '100' into '100'"); + } + { + String input = "hello"; + final InvocationTargetException exception = assertThrows(InvocationTargetException.class, () -> method.invoke(null, input)); + Throwable targetException = exception.getTargetException(); + assertEquals(IllegalArgumentException.class, targetException.getClass(), methodName + " should have thrown an instance of 'IllegalArgumentException'"); + assertEquals(input + " cannot be converted into a 'int' value. Exiting program.", targetException.getMessage()); + } + } catch (NoSuchMethodException e) { + fail("Can't find a method with name " + methodName + " in class " + classToFind + " with 1 parameter of type 'String'"); + } } } From 1f11877b5f8740e2deea3b2d2286d786336ac40f Mon Sep 17 00:00:00 2001 From: hhimanshu Date: Sat, 23 May 2020 17:59:13 -0700 Subject: [PATCH 28/29] Added m6_05_testGetFloatValueExistenceAndCorrectness --- src/test/java/com/h2/Module06_Test.java | 30 +++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/src/test/java/com/h2/Module06_Test.java b/src/test/java/com/h2/Module06_Test.java index af67a2a5b..e02f67516 100644 --- a/src/test/java/com/h2/Module06_Test.java +++ b/src/test/java/com/h2/Module06_Test.java @@ -101,4 +101,34 @@ public void m6_04_testGetIntValueExistenceAndCorrectness() throws IllegalAccessE fail("Can't find a method with name " + methodName + " in class " + classToFind + " with 1 parameter of type 'String'"); } } + + @Test + public void m6_05_testGetFloatValueExistenceAndCorrectness() throws IllegalAccessException, InvocationTargetException { + final String methodName = "getFloatValue"; + final Optional> maybeClass = getUtilitiesClass(); + assertTrue(maybeClass.isPresent(), classToFind + " should be present"); + assertEquals(classToFind, maybeClass.get().getCanonicalName()); + + final Class aClass = maybeClass.get(); + try { + Method method = aClass.getMethod(methodName, String.class); + assertTrue(isPublic(method), methodName + " must be declared 'public'"); + assertTrue(isStatic(method), methodName + " must be declared 'static'"); + assertEquals(float.class, method.getReturnType(), methodName + " must have a 'float' return type"); + + { + float result = (float) method.invoke(null, "123.12"); + assertEquals(123.12f, result, methodName + " should convert '123.12' into '123.12f'"); + } + { + String input = "hello"; + final InvocationTargetException exception = assertThrows(InvocationTargetException.class, () -> method.invoke(null, input)); + Throwable targetException = exception.getTargetException(); + assertEquals(IllegalArgumentException.class, targetException.getClass(), methodName + " should have thrown an instance of 'IllegalArgumentException'"); + assertEquals(input + " cannot be converted into a 'float' value. Exiting program.", targetException.getMessage()); + } + } catch (NoSuchMethodException e) { + fail("Can't find a method with name " + methodName + " in class " + classToFind + " with 1 parameter of type 'String'"); + } + } } From 9287a2af96853e114a5d903218e5e9aa6023a0d5 Mon Sep 17 00:00:00 2001 From: hhimanshu Date: Sat, 23 May 2020 18:16:31 -0700 Subject: [PATCH 29/29] Added m6_06_testMainMethodPrintsCorrectMortgageAmount --- src/test/java/com/h2/Module04_Test.java | 4 +-- src/test/java/com/h2/Module06_Test.java | 42 +++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 2 deletions(-) diff --git a/src/test/java/com/h2/Module04_Test.java b/src/test/java/com/h2/Module04_Test.java index 0ad1deefc..61e0181b6 100644 --- a/src/test/java/com/h2/Module04_Test.java +++ b/src/test/java/com/h2/Module04_Test.java @@ -17,7 +17,7 @@ import static org.junit.platform.commons.util.ReflectionUtils.*; public class Module04_Test { - private final String classToFind = "com.h2.MortgageCalculator"; + private static final String classToFind = "com.h2.MortgageCalculator"; private final InputStream systemIn = System.in; private final PrintStream systemOut = System.out; @@ -50,7 +50,7 @@ private static Optional> getClass(final String className) { return aClass.toOptional(); } - public Optional> getMortgageClass() { + public static Optional> getMortgageClass() { return getClass(classToFind); } diff --git a/src/test/java/com/h2/Module06_Test.java b/src/test/java/com/h2/Module06_Test.java index e02f67516..7dfc08883 100644 --- a/src/test/java/com/h2/Module06_Test.java +++ b/src/test/java/com/h2/Module06_Test.java @@ -5,7 +5,10 @@ import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; +import java.util.Arrays; +import java.util.List; import java.util.Optional; +import java.util.stream.Collectors; import static org.junit.jupiter.api.Assertions.*; import static org.junit.platform.commons.util.ReflectionUtils.*; @@ -131,4 +134,43 @@ public void m6_05_testGetFloatValueExistenceAndCorrectness() throws IllegalAcces fail("Can't find a method with name " + methodName + " in class " + classToFind + " with 1 parameter of type 'String'"); } } + + @Test + public void m6_06_testMainMethodPrintsCorrectMortgageAmount() throws NoSuchMethodException { + final String methodName = "main"; + + final Optional> maybeMortgageCalculator = Module04_Test.getMortgageClass(); + assertTrue(maybeMortgageCalculator.isPresent(), classToFind + " must exist"); + final Class mortgageCalculator = maybeMortgageCalculator.get(); + + final Method[] methods = mortgageCalculator.getDeclaredMethods(); + + final List filteredMethod = Arrays.stream(methods).filter(method -> method.getName().equals(methodName)).collect(Collectors.toList()); + assertEquals(1, filteredMethod.size(), classToFind + " should contain a method called '" + methodName + "'"); + + final String loanAmount = "264000"; + final String termInYears = "30"; + final String annualRate = "3.74"; + String input = "hello"; + + Method method = mortgageCalculator.getMethod("main", String[].class); + { + final InvocationTargetException exception = assertThrows(InvocationTargetException.class, () -> method.invoke(null, (Object) new String[]{input, termInYears, annualRate})); + Throwable targetException = exception.getTargetException(); + assertEquals(IllegalArgumentException.class, targetException.getClass(), methodName + " should have thrown an instance of 'IllegalArgumentException'"); + assertEquals(input + " cannot be converted into a 'long' value. Exiting program.", targetException.getMessage()); + } + { + final InvocationTargetException exception = assertThrows(InvocationTargetException.class, () -> method.invoke(null, (Object) new String[]{loanAmount, input, annualRate})); + Throwable targetException = exception.getTargetException(); + assertEquals(IllegalArgumentException.class, targetException.getClass(), methodName + " should have thrown an instance of 'IllegalArgumentException'"); + assertEquals(input + " cannot be converted into a 'int' value. Exiting program.", targetException.getMessage()); + } + { + final InvocationTargetException exception = assertThrows(InvocationTargetException.class, () -> method.invoke(null, (Object) new String[]{loanAmount, termInYears, input})); + Throwable targetException = exception.getTargetException(); + assertEquals(IllegalArgumentException.class, targetException.getClass(), methodName + " should have thrown an instance of 'IllegalArgumentException'"); + assertEquals(input + " cannot be converted into a 'float' value. Exiting program.", targetException.getMessage()); + } + } }