package junit.learnnow;

import static org.junit.Assert.*;
import java.io.IOException;
import org.junit.*;

public class MyClassTest {

	@BeforeClass
	public static void setUpClass() throws Exception {
		// Code executed before the first test method in the JUnit is run.
		System.out.println("setUpClass()");
	}

	@AfterClass
	public static void tearDownClass() throws Exception {
		// Code executed after the last test method in the JUnit is run.
		System.out.println("tearDownClass()");
	}

	@Before
	public void setUp() throws Exception {
		// Code executed before each test
		System.out.println("setUp()");
	}

	@After
	public void tearDown() throws Exception {
		// Code executed after each test
		System.out.println("tearDown()");
	}

	@Test
	public void testPlay() {

		/*
		 * Warning: For objects it uses the equals() method to look for
		 * equality!
		 */

		System.out.println("in testPlay()");
		;

		MyClass c1 = new MyClass();
		MyClass c2 = c1;

		assertEquals(1, 2 - 1); // interger
		assertEquals(10.0, 10.0, .001); // double - using common delta value of
										// .001
		String myString = "JUnit Hello World";
		assertEquals("JUnit Hello World", myString);
		// Better: Same as the above but giving a description of the test.
		assertEquals("Testing the creationg of myString", "JUnit Hello World",
				myString);
		assertSame(c1, c2); // for Objects only!
		assertTrue(true);
		assertFalse(false);
		assertNull(null);
		assertNotNull(c1);

		// Uncomment next line and test! Look at the error.
		// assertEquals("Ooops", myString);

		// Used for stubbed out tests before you know what to test for.
		// fail("Not yet implemented");

	}

	@Test
	public void testMyMethodInt() {
		MyClass c1 = new MyClass();
		assertEquals(0, c1.myMethodInt(-1));
		assertEquals(0, c1.myMethodInt(0));
		assertEquals(0, c1.myMethodInt(10));
		assertEquals(1, c1.myMethodInt(11));
		// Next line will error out.
		// assertEquals(1, c1.myMethodInt(0));
	}

	@Test
	public void testMyMethodDouble() {
		MyClass c1 = new MyClass();
		assertEquals(10.0, c1.myMethodDouble(100.0), .000);
		assertEquals(10.0, c1.myMethodDouble(100.0), .001); // Common to add the
															// .001 for decimal
															// delta issues.
	}

	@Test
	public void testMyMethodBoolean() {
		MyClass c1 = new MyClass();
		assertEquals(true, c1.myMethodBoolean(true));
		assertTrue(c1.myMethodBoolean(true));
		assertFalse(c1.myMethodBoolean(false));
	}

	@Test
	public void testMyMethodString() {
		MyClass c1 = new MyClass();
		// Test all the situations!
		assertEquals("You won!", c1.myMethodString("Hello World"));
		assertEquals("No", c1.myMethodString("Hello"));
		assertEquals(null, c1.myMethodString(null));
		// Example using the assertNull & assertNotNull methods.
		assertNull(c1.myMethodString(null));
		assertNotNull(c1.myMethodString("Hello World"));
	}

	@Test
	public void testGoodHouseLoanRate() {
		MyClass myClassObj1 = new MyClass();
		myClassObj1.setHouseLoanRate(3.0);
		assertTrue(myClassObj1.goodHouseLoanRate());
		myClassObj1.setHouseLoanRate(4.0);
		assertFalse(myClassObj1.goodHouseLoanRate());
	}

	@Test
	public void testDisplayFile() {
		MyClass myClassObj1 = new MyClass();
		String myInfo = null;
		try {
			myInfo = myClassObj1.displayFile("BooBoo.txt");
			fail("File was supposed to not exist!");
		} catch (IOException e) {
			// The string should be null because the file should not exit!
			assertNull(myInfo);

			// Note: If we expected the file to be there then we could test this
			// way:
			// fail("File should have existed!\n" + e.getMessage());

		}
	}

	@Test
	public void testPrivateMethod() {
		MyClass myClass = new MyClass();

		try {
			//Test calling a private method with an int.
			java.lang.reflect.Method method = MyClass.class.getDeclaredMethod(
					"examplePrivateMethod", int.class); //NOTE how an int parm is specified.
			method.setAccessible(true);
			//method.invoke() returns a class!
			int result = (Integer) method.invoke(myClass, 10); //Note that only an Object is returned so cast Wrapper class.
			assertEquals(10, result);
		} catch (Exception e) {
			fail("Ooops... developer's code is bad.");
		}

	}

	@Test
	public void testPrivateMethod2() {
		MyClass myClass = new MyClass();
		
		try {
			//Test calling a private method with a String parm.
			java.lang.reflect.Method method = MyClass.class.getDeclaredMethod(
					"examplePrivateMethod2", String.class); //NOTE this 1 of 2 changes!
			method.setAccessible(true);
			//method.invoke() returns an Object!
			String result = (String) method.invoke(myClass, "Hello"); //NOTE this 2 of 2 changes!
			assertEquals("Hello", result);
		} catch (Exception e) {
			fail("Ooops... developer's code is bad.");
		}

	}

	@Test
	public void testPrivateMethod3() {
		MyClass myClass = new MyClass();
		
		try {
			//Test calling a private method with a 2 String parms.
			java.lang.reflect.Method method = MyClass.class.getDeclaredMethod(
					"examplePrivateMethod3", String.class, String.class);  //NOTE this 1 of 2 changes!
			method.setAccessible(true);
			//method.invoke() returns an Object!
			String result = (String) method.invoke(myClass, "Hello ", "World"); //NOTE this 2 of 2 changes!
			assertEquals("Hello World", result);
		} catch (Exception e) {
			fail("Ooops... developer's code is bad.");
		}

	}

}
