jforrest1980
jforrest1980

Reputation: 19

Unit Testing toStrings in JAVA

How do you test a toString in JAVA? I imagine this is the same concept as regular testing, but I am really having a lot of issues. I can not find any of this information in my Big JAVA textbook. I have read all the chapters we have covered at least 5 times not. I just don't see it, and this was never covered in any of the homework.

For one, I don't understand where in the unit test where the code is provided in the first example, my teacher put "num" in assertTrue(text.contains(num));

I figured that she put num because we were following the format of the WholeLife Policy. Ex.

WholeLifePolicy policy = new WholeLifePolicy(num, value, years, name);

I thought since this was an example, I would then do the same and for example for the face value as shown below.

assertTrue(text.contains("Face Value:"));
        assertTrue(text.contains(value));

This doesn't compile because it says it is not compatible because the number is a double. So I tried double. The only thing that compiles is "num"

So obviously none of my tests are passing. Here is my code. for the WholeLifePolicy class, follow by the test class.

Why is "num" used? Is it becasue it is an explicit parameter of the policy object? Or is is just because a number is in there" Or another reason?

Obviously all my code is below the //comments. Everything else was provided in the lab source.

 /**
     * Return a string representation of the WholeLifePolicy.
     *
     * @return String  output string.
     *
     *  <pre>
     *  Produce output in the following format:
     *
     *  Policy Information:
     *  Policy #: WLP1000000
     *  Policy Years: 20
     *  Face Value: 50000.0
     *  Beneficiary: John Doe
     *
     *  </pre>
     */
    public String toString()
    {
        String output = "Policy Information:\n";
        output = output + "Policy #: " + this.getPolicyNum() + "\n";

        // your code here, finish the output string
        output = output + "Face Value" + this.getFaceValue() + "\n";
        output = output + "Policy Years:" + this.getPolicyYrs() + "\n";
        output = output + "Beneficiary" + this.getBeneficiary() + "\n";
        return output;

    }

}

TEST CLASS:

 /**
     * Test the toString method.
     */
    @Test
    public void testToString()
    {
        String num = "WLP1234567";
        double value = 50000.0;
        int years = 20;
        String name = "Katie Perry";
        WholeLifePolicy policy = new WholeLifePolicy(num, value, years, name);

        String text = policy.toString();
        assertTrue(text.contains("Policy Information:"));

        assertTrue(text.contains("Policy #:"));
        assertTrue(text.contains(num));

        // your code here, finish the testing of the toString() method
        // checking for both the headings and face value, policy years
        assertTrue(text.contains("Face Value:"));
        assertTrue(text.contains(num));


        assertTrue(text.contains("Policy Years:"));
        assertTrue(text.contains(num));

        assertTrue(text.contains("Beneficiary:"));
        assertTrue(text.contains(num));



    }
}

Upvotes: 1

Views: 269

Answers (3)

Nathan Hughes
Nathan Hughes

Reputation: 96385

The thing you're testing doesn't have any dependencies that are hard to mock. Testing this should be easy. Using multiple tests using contains is actually error-prone, because it's introducing complexity. Keep this simple and straightforward.

This could be as easy as

@Test 
public void toString() {
    WholeLifePolicy policy = new WholeLifePolicy("WLP1234567", 
    50000.0, 20, "Katie Perry");
    String expected = "Policy Information:\nPolicy #: WLP1000000\n" 
    + "Policy Years: 20\nFace Value: 50000.0\nBeneficiary: John Doe\n";
    assertEquals(expected, policy.toString());
}

This checks that the values you entered are represented as you expect them. If the assertion fails then the error message will tell you where the mismatch is. Hard-coding the expected string is fine, you are not required to use the same values you used to set up the test. If you did then you'd be duplicating the same code that you used in the method you were testing, which would be a lot of work (not just upfront, but every time the code changed).

The biggest real-world complication here is the use of newlines. Typically developers might run tests locally on corporate-mandated Windows and have the tests executed by CI on some other platform with different line-endings. If I wanted this to work regardless of line-ending I'd change the toString to use System.getProperty("line.separator") and I'd change the test to something like

static String lines(List<String> strings) {
    String delimiter = System.getProperty("line.separator");
    StringBuilder builder = new StringBuilder("");
    for (String s : strings) {
        builder.append(s);
        builder.append(delimiter);
    }
    return builder.toString();
}

@Test 
public void testToString() {
    WholeLifePolicy policy = new WholeLifePolicy("WLP1234567", 
    50000.0, 20, "Katie Perry");
    List<String> expectedLines = new ArrayList<String>();
    expectedLines.add("Policy Information:");
    expectedLines.add("Policy #: WLP1000000");
    expectedLines.add("Policy Years: 20");
    expectedLines.add("Beneficiary: John Doe");
    assertEquals(lines(expectedLines), policy.toString());
}

Actually because a) I'm lazy and b) newlines in toStrings make for disorganized-looking log files, I avoid using line separators in toString methods.

This may be an exercise set up to teach about how to call methods, and how to look up the API documentation (both of which are important survival skills). The String#contains method takes a CharSequence as a parameter (which String implements), so you need to convert your variable to a String to use it. If you have a reference type you can call toString on it, for primitives you can look up the wrapper type and either convert the primitive to a wrapper type or find a static method that takes the primitive and converts it to a String (see the API documentation for java.lang.Double).

Upvotes: 1

sahlix
sahlix

Reputation: 61

Obviously you have to complete your test for the missing values. Num is already tested to be contained in the toString method.

Now you are supposed to test for the remaining properties to be contained in the output of the toString method.

For instance you could use an empty string to force conversion to string:

assertTrue(text.contains("Face Value:"));
// this converts 'value' to string
assertTrue(text.contains("" + value)); 

This method should also work:

assertTrue(text.contains(Double.toString(value)));

Upvotes: 0

wihoho
wihoho

Reputation: 36

You may parse the double type value into a string when performing the tests.

Upvotes: 0

Related Questions