Testing a method that takes a String argument with JUnit theories
I am very new to Unit theories. I have a parse () method that takes an html string as input and returns a document (DOM of an 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 edge cases I want to check are as follows:
- Empty line
- Empty string (string with spaces)
- Zero line
- Non Html String
- Valid HTML String
In the case of the first 3, it should throw an IllegalArgumentException. In the case of the latter 2, it returns a valid document object. I was able to write a test for the first 2. But I'm 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 is not called for the String = null argument. Can anyone help me with checking the last 3 cases?
Console o / p:
called
0
called
1
source to share
So, I believe this post answers the question about usage null
in @DataPoints
. JUnit 4.12 error when using a theory method + enum + DataPoint that contains null .
It looks like it @DataPoints
doesn't use the type of the declared field to determine the input type Theory
. Instead, it analyzes each actual value. Because of this, it is null
not attached to String
, but to Object
. And the premise is that null
you shouldn't provide every argument c Theory
.
Hence, it seems that you cannot use null
in @DataPoints
. As already pointed out, you need to use @DataPoint
. However, instead of having 3 values @DataPoint
, you could do the following ...
@DataPoints
public static String[] nonNullValues = new String[]{"", " "};
@DataPoint
public static String nullValue = null;
However, I have another solution. I recently discovered @TestedOn . This allows:
@Theory
public void testIt(@TestedOn(ints={3,4,5}) int value){...}
Unfortunately, it @TestedOn
was only implemented for int
. I have implemented my own @TestOn which allows all primitive types. Thus, your test can be successfully written as:
@Theory
public void testIt(@TestOn(strings={"", " ", TestOn.NULL}) String value){...}
This will be correctly checked for null
. I really liked this mechanism because it allows values Theory
to be matched against individual tests.
source to share
When you use @DataPoint instead of @DataPoints and separately assign three combinations to different strings, it works and calls the test () method even if 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. I just wanted to leave it here to make it easier to find.
PS2: If you know this is a bug or a JUnit feature, or if there is another way to fix it by keeping @DataPoints, please share this information here.
source to share
Just try upgrading JUnit to release 4.12 .
The problem has been fixed.
For details, see the URLs below:
- https://github.com/junit-team/junit/pull/529
- https://github.com/junit-team/junit/blob/master/doc/ReleaseNotes4.12.md :
Until JUnit 4.11 the field of a @DataPoints-annotated array cannot contain null values, but the array returned by the @ DataPoints-annotated method could not. This asymmetry has been resolved: both can now provide a data zero point.
source to share