Nemin
Nemin

Reputation: 2037

Test a method that takes an String argument with JUnit theories

I am very new to JUnit theories. I have a method parse() that takes a html String as an input and returns a Document (DOM of the HTML Document)

public Document parse(final String inputString) throws IllegalArgumentException {
    if (StringUtil.isBlank(inputString))
        throw new IllegalArgumentException("Input HTML String is empty,blank or null");
    return Jsoup.parse(inputString, "", Parser.xmlParser());
}

I wanted to write unit tests for this using Junit theories. The boundary cases that I want to check are:

In case of first 3, it should throw an IllegalArgumentException. In case of the last 2, it returns a valid Document Object. I have been able to write the test for the first 2. But I am not sure how to test the last 3 using Junit Theories.

Here's what I have so far:

    @Rule
    public ExpectedException thrown = ExpectedException.none();

    @DataPoints
    public static String[] function(){
        return new String[]{
                ""," ",null
        };
    }
    @Theory
    public void test(String s) {
        System.out.println("called");
        if(s==null)
            System.out.println("null");
        System.out.println(s.length());
        thrown.expect(IllegalArgumentException.class);
        htmlAssessment.parse(s);    
    }

For some reason, the test method isnt called for the argument String = null. Could someone help me with testing the last 3 cases?

Console o/p:

called
0
called
1

Upvotes: 3

Views: 1712

Answers (3)

ROMANIA_engineer
ROMANIA_engineer

Reputation: 56694

Just try to upgrade your JUnit to release 4.12.

The problem was fixed.

See the below URLs for many details:

Upvotes: 0

John B
John B

Reputation: 32969

So I believe this post answers the question about using null in @DataPoints. JUnit 4.12 issue when using theory + enum type + DataPoint that contains a null.

It appears that @DataPoints does not use the type of the declared field to determine the type of the Theory input. Instead it analyzes each actual value. Because of this null is not being linked to String but to Object. And the premise is that null should not be provided to every argument in a Theory.

Hence, it appears that you cannot use null in @DataPoints. As has been pointed out, you would need to use @DataPoint. However, rather than having 3 @DataPoint values you could do the following...

@DataPoints
public static String[] nonNullValues = new String[]{"", " "};
@DataPoint
public static String nullValue = null;

However, I do have another solution. Recently I discovered @TestedOn. This allows for the following:

@Theory
public void testIt(@TestedOn(ints={3,4,5}) int value){...}

Unfortunately @TestedOn was only implemented for int. I implemented my own @TestOn that allows for all the primitive types. So your test could successfully be written as:

@Theory
public void testIt(@TestOn(strings={"", " ", TestOn.NULL}) String value){...}

This will correctly test on null. I have really liked this mechanism because it allows me to map Theory values to individual tests.

Upvotes: 4

t.pimentel
t.pimentel

Reputation: 1575

When you use @DataPoint instead of @DataPoints and individually assigns the three combinations to different Strings it works and it calls the test() method even when the String is null.

@DataPoint public static String input1 = "";
@DataPoint public static String input2 = " ";
@DataPoint public static String input3 = null;

PS: @Nemin found the answer to his own question. Just wanted to leave it here so it's easier to find.

PS2: If you know if this is a bug or a feature of JUnit, or if there's another way to solve it keeping @DataPoints, please do share this information here.

Upvotes: 1

Related Questions