Starting from:

$35

Activity: Static Members and Junit Solution

Goals:

By the end of this activity you should be able to do the following:

    • Understand and implement static variables and methods

    • Be able to create, compile, and run a JUnit test file

Description:

For this assignment, you will need to download BankLoan.java from the course website and save it to an appropriate folder.

Directions:

Don’t forget to add your Javadoc comments for your classes, constructor, and methods in this activity.

Part 1: Static methods

    • You don't have to read this bullet now, but make sure that you understand it before this week's quiz and project. Three of the properties of static methods:
o  Static methods can be invoked using the name of the class.

o  Static methods can be invoked before an object of the class is instantiated.

o Static methods cannot access instance data. This is because the method can be called before an object is created, which means no instance data would exist. Consider the following examples:

        ◦ The trim method of the String class is an instance method. You must create a String object before you call the method so that the method knows what to trim:

String s = " Red Sox"; System.out.println(s.trim()); Red Sox
        ◦ The pow method of the Math class has parameters for the values it needs so it is defined as static. This means that you don't have to go through the additional step of creating a Math object before you use the method:
System.out.println(Math.pow(2, 3)); 8.0

If a method that you create doesn't need direct access to instance variables or instance methods in that class, then you should consider making the method static.

    • Suppose that you want to add a method to BankLoan that returns true if a loan amount is valid and false otherwise. If the loan amount (a double) is taken as a parameter, then the method would not need direct access to instance data. Create the following method header:

public static ________ isAmountValid(________ amount)

Add code to the method to return true if the amount is greater than or equal to 0 and false otherwise:

return amount ___ 0;




Page 1 of 7
Activity: Static Members and JUnit    Page 2 of 7


    • Make sure that BankLoan.java compiles after you add your isAmountValid method. It will be tested later in this activity.

    • Now suppose that you need a method that returns true if a loan's balance is greater than 0 and false otherwise. The user will pass in a BankLoan object as a parameter, and the method will only access this object, which is considered a local variable. Thus, the method can be static.

public static ________ isInDebt(________ loan) {

    • Now add an if statement that returns true if the specified object has a balance greater than 0:

if (_________.getBalance() > 0) {

return true;
}
return ________;

    • Compile your program and test it in the interactions pane:

BankLoan b = new BankLoan("Bob", 0.08);


BankLoan.isInDebt(b)
false

b.borrowFromBank(1); // borrow $1.00
BankLoan.isInDebt(b)
true

Part 2: Static variables as fields – a.k.a. class variables as opposed to instance variables

    • You don't have to read this bullet now, but make sure that you understand it before this week's quiz and project. Properties of static variables / constants:
o Public constants (which are static and final) can be accessed using the name of the class if they are public.

o  Public static constants can be accessed before an object of the class is instantiated.

System.out.println(Math.PI); 3.141592653589793

o Public static variables (not declared as final) violate encapsulation. Private static variables should be accessed and modified through static or instance methods.

o A static variable is shared among all instances of the class and it can be accessed / modified by any method in the class. Why are constants declared as static as well as final?

If one object modifies a static variable, then it will be modified for all other objects as well because they are all accessing the same variable (i.e., a class variable is shared). If a variable needs to be specific to one object (e.g., each object need its own customer name field), then it should an instance variable (not static) rather than a class variable (static).

    • Add a static variable to the BankLoan class that will count the number of BankLoan objects that have ever been instantiated in a program. The value will be initialized to 0 and then be incremented each time a BankLoan object is created.

private static int loansCreated = 0;


Page 2 of 7
Activity: Static Members and JUnit    Page 3 of 7




    • You want to increment the variable only when an object is instantiated, so you'll need to add the following code to the constructor:

loansCreated++;

    • You'll also need to add a method to access the variable. The method will only access a static variable, so it can and should be static as well.

public static ________ getLoansCreated() {

return loansCreated;
}

    • Also add a method that will reset the number of loans created to 0. The method only modifies a static variable, so it can be static and there is no return type.

public static _________ resetLoansCreated() {

________ = _________;
}

Test your class in the interactions pane:

BankLoan.getLoansCreated()


0
BankLoan jane = new BankLoan("Jane L", 0.09); BankLoan bob = new BankLoan("Bob S", 0.09);

Now open a canvas window (click on the Debug tab), then drag jane and bob onto the canavas. Unfold jane in the Debug tab, and drag loansCreated onto the Canvas. Figure 1 shows the initial canvas. Notice that loansCreated is shown as BankLoan.loansCreated since it is a class variable rather than an instance variable.

BankLoan.getLoansCreated()

2
bob = new BankLoan("Bob Parker", 0.02);

Figure 2 shows the canvas after bob has been assigned a new loan and the loansCreated field has been updated. That is, we have now called the new operator a total of three times.

BankLoan.getLoansCreated()

3

BankLoan.resetLoansCreated();
BankLoan.getLoansCreated()
0













Page 3 of 7
Activity: Static Members and JUnit    Page 4 of 7




























Figure 1. Canvas after jane and bob are created




























Figure 2. Canvas after bob is reassigned to a new BankLoan









Page 4 of 7
Activity: Static Members and JUnit    Page 5 of 7


Part 3. JUnit Test Files – NOTE: JUnit is installed on all the computers in the lab. In order to use JUnit on you own computer, you must download and unzip JUnit (as you did Checkstyle), and then JUnit must be configured in jGRASP (Tools > JUnit > Configure). You may want to do Part 3 on the lab computer if you don’t have JUnit installed on your own machine. Note that the following example will work with the unmodified BankLoan.java file.

Now let’s create a JUnit test file to allow us to test (and retest) the method in a class. Suppose we want to test the chargeInterest() method. We’ll need to create a test method that essentially includes the statements that we would enter as interactions to informally test the chargeInterest() method.

    • For example, we could test this method using interactions by entering the following:

BankLoan loan1 = new BankLoan("Jane", .10); loan1.borrowFromBank(1000.00); loan1.chargeInterest() loan1.getBalance()

1100.0

    • Create a project file for the BankLoan class. After you have created the project and added BankLoan.java to it, you should see the following in the Open Projects section of the Browse tab.











    • With BankLoan.java open in the CSD Window, on the Desktop menu click on the Create JUnit Test File button .



    • This creates a JUnit test file name BankLoanTest.java that is listed in the “Test File category in the Project tab.
















Page 5 of 7
Activity: Static Members and JUnit    Page 6 of 7


    • BankLoanTest.java contains a class with the same name. The class contains a setup() method and test method named defaultTest() that asserts that 0 equals 1 which will always fail. This is an example test method that you should comment out, modify, or delete.

/** A test that always fails. **/

@Test public void defaultTest() {
Assert.assertEquals("Default test added by jGRASP. Delete "

+ "this test once you have added your own.", 0, 1);
}

    • Either modify the method above or create a new test method as follows. If you create a new method, be sure to delete or comment out the default test method. Note that we won’t be using the setup() method, so it can be deleted or left as is since it has an empty body.

@Test public void chargeInterestTest() { BankLoan loan1 = new BankLoan("Jane", .10); loan1.borrowFromBank(1000.00); loan1.chargeInterest();
Assert.assertEquals(" ", 1100, loan1.getBalance(), .000001);
}

Note that the third parameter is the “delta” required when two doubles values are compared for equality (i.e, how close do the values have to be to be considered equal; in this case, we have chosen 0.000001).

    • After you have entered your test method, you can compile  the test file or you can compile and run  the test file using JUnit buttons on the Project tab or on desktop menu. You should make sure BankLoanTest compiles successfully before you run it.

    • A successful test will have output such as the following output in the Run I/O tab and in the JUnit results window

Runing 1 JUnit test. Completed 1 tests 1 passed

Ï

    • To test other methods in the BankLoan class, you simply create additional @Test methods in BankLoanTest.java using the procedure above. Remember creating a test method is only slightly more effort than manually testing your method in interactions the first time. In fact, many of the same statements used in interactions are used in the test method. These are then followed by an appropriate JUnit assert statement. As you create new methods in a class, you can also create appropriate test methods in the corresponding test class. This helps ensures each new method is correct before you proceed to the next method. Being able re-run all test files with a single click is a huge time saver as you build your program incrementally and make changes during development.



Page 6 of 7
Activity: Static Members and JUnit    Page 7 of 7


    • If a test method fails, set a breakpoint at or above the assert that failed, then run the test file using the test file debugger  button. When the program stops at the breakpoint, drag variables onto the canvas and examine the values. Hopefully, you’ll be able to see the problem and correct the error. Remember that if a test method fails, either the method you are testing has an error or the test method itself has an error. You may need to step in at the

statement that calls the method you are testing. For example, stepping in at loan1.chargeInterest() will take you into the chargeInterest method where you can step through it looking for a problem. Figure 3 shows the jGRASP desktop after stopping at the breakpoint and then stepping one time to create loan1. Figure 4A shows the canvas after loan1 has been dragged onto it but before any methods have been called on loan1. Figure 4B shows the canvas after calling the borrowFromBank and chargeInterest methods on loan1.

























Figure 3. Running BankLoanTest in the Debugger, after stopping at the breakpoint and then stepping one time to create loan1.
















Figure 4A. Canvas with loan1 after it was created but before calling borrowFromBank.















Figure 4B. Canvas after calling the borrowFromBank and chargeInterest methods.

Finally, submit your BankLoan.java and BankLoanTest.java files to Web-CAT.


Page 7 of 7

More products