Assert statement for junit - java

My method returns null sometimes and not null values so how to write a assert for those scenarios
example:assertNotNull(some statement)

Simple:
#Test
public void testFooGivesNotNull() {
assertNotNull(foo.bar(somethingLeadingToNotNull));
}
#Test
public void testFooGivesNull() {
assertNull(foo.bar(somethingElseLeadingToNull));
}
In other words: you do that by identifying the possible test cases, to then write at least one test for each of the possible paths.
And for the record: returning null is rarely a good idea. That null is the first step towards running into a NullPointerException. Consider alternatives, such as
returning a special object that represents "null"
returning an Optional
throwing an exception

Just call your function and add an error message:
Assert.assertNotNull(someFunction(), "This should not be null");

A good way to use Assert.assertNotNull is via static import.
import static org.junit.Assert.assertNotNull;
assertNotNull(yourValueTobeCheckAsNull, "This should not be null");

Related

Should I assert or throw an exception in a junit library?

I'm writting a java library to easily write some junit tests. I don't know if I must assert inside my library or throw an exception. Here is an example. Asuming I define, in my library, this function to check the number of methods of class
public void assertNumberOfMethods(Class clazz, int expectedNumberOfMethods) {
int numberOfMethods = clazz.getDeclaredMethods().length;
//TODO compare number and expected number
}
Should I
Directly assert inside my library
Assert.assertTrue(expectedNumberofMethod > 0);
Assert.assertEquals(numberOfMethods,expectedNumberOfMethods);
//...
Throw an exception an let the user handle this exception. Since this library is designed to be used in unit tests, the user will be able to catch some of this exception using #Test(expected=SomeCustomException.class)
public void assertNumberOfMethods(Class clazz, int expectedNumberOfMethods) throws IllegalArgumentException, SomeCustomException {
if(expectedNumberOfMethods <= 0)
throw new IllegalArgumentException(/*...*/);
int numberOfMethods = clazz.getDeclaredMethods().length;
if(numberOfMethods != expectedNumberOfMethods)
throw new SomeCustomException(/*...*/);
}
EDIT This is a dummy example
Your are planning to create specialized assert methods, like as you would write an extension to the Assert class.
For this you should directly throw assert errors (variant 1), as the assert methods in Assertdo, providing a helpful error message.
The possibility to specify expected exceptions in the #Test annotation serves a different purpose. With this annotation Junit allows you to test that a piece of code throws an expected exception, without the need in the test code to catch the exception.
I would use the junit fail() method that is used in pretty much all other assert methods in the junit library
public void assertNumberOfMethods(Class clazz, int expectedNumberOfMethods) {
int numberOfMethods = clazz.getDeclaredMethods().length;
if (numberOfMethods != expectedNumberOfMethods) {
fail("some failing message);
}
}
You should throw a java.lang.AssertionError exception if an assertion is false.
Also, try not to re-invent the wheel, take a look at AssertJ which does exactly what you want.
// Example
assertThat(clazz.getDeclaredMethods()).hasSize(5);
expectedNumberofMethod > 0 should be an IllegalArgumentException. The test has not failed, the method has been called incorrectly.
numberOfMethods == expectedNumberOfMethods should throw a java.lang.AssertionError (or a like), how you do this is up to you, you could use Assert.assertThat, but it binds you to a test framework. You could throw it directly, but you have to do more manual work.
If you use Assert.assertThat, remember that the first argument can be a String description of what went wrong. Use it.
Don't use custom exceptions (that do not extent java.lang.AssertionError), think about what the users of your API will be expecting, and do that. Every other assert causes a java.lang.AssertionError to be throw, but you are doing something different.

What is the best runtime exception to use when mandatory input is missing

I have service, a simple class that need to take input and run some business logic. Before executing this service, the user must set all the data. In general, it look like this:
public class TestService extends InnerServiceBase {
/**
* Mandatory input
*/
private Object inputObj;
#Override
protected ErrorCode executeImpl() {
//Some business logic on inputObj
return null;
}
public void setInputObj(Object inputObj) {
this.inputObj = inputObj;
}
}
What is the best runtime exception to throw in case the inputObj is null ?
IllegalStateException seems like the best fit. The object is not in the correct state to have executeImpl() called on it. Whatever exception you use, make sure the error message is helpful.
Whether you should be using an unchecked exception at all is a whole other question...
Depends on the scenario.
If this is part of an API that another developer is using, throwing NullPointerException is reasonable since you don't want that input to be null. Adding a descriptive exception message would be helpful.
If you're not interested in throwing an NPE, or this is part of code that's not going into an API, then you could throw an IllegalArgumentException, as null could be considered an illegal argument.
If setInputObj is called with a null argument, and that's not valid, then throw NullPointerException. There's some debate over the "correct" exception here (IllegalArgumentException or NullPointerException for a null parameter?), but Guava, Apache Commons Lang and even the JDK itself (Objects.requireNonNull) have settled on NPE.
If executeImpl is called before inputObj has been set, throw IllegalStateException.

JUnit test another method that uses fail()

We have a rather complex object that is the result of calling our drools engine.
For JUnit testing our rules we create a RulesTestHelper class that offers a method "assertOurObject(OurObject expected, OurObject actual)" and does many assertions on the elements of OurObject (This might probably be solved better by writing our own Matcher but we aren't that far yet).
Now in our method "assertOurObject" the first check is done if any of the objects is null, like this:
if (expected == null || actual == null)
fail("Expected or actual is null");
Now I want to JUnit test this method and assert that when I set one of the two objects to "null" I will fail the test. So in other words, I expect the test to fail and this should be ok.
Is this possible and if so, how?
If you don't want to change your code, you can use a solution similar to what Anderson Vieira said but instead use
#Test(expected=AssertionError.class)
The junit fail() method throws an AssertionError that you can specifically expect
You could throw an exception when this case occurs and tell the test to expect it by annotating it with:
#Test(expected=NullPointerException.class)
public void testShouldFailIfAnyObjectIsNull() {
... // do something
if (expected == null || actual == null) {
throw new NullPointerException();
}
... // do something
}

Junit- how to test invalid usage of parameters

I am supposed to write a Junit test for the invalid usage of correct parameters. I am a bit confused by this concept. Can someone please help to explain what is this scenario, and how to do this with an example?
I am testing a method that take a customer and a type of service as parameters. and I've tried the assertFalse method below, and tried to pass two customers to
assertFalse("Registration fails for add two services to one customer", cs.addPeople("Jack", "Jill","Cleaning"));
I realized that this is not the correct way as the add.People()method only takes one person as a parameter. In this case how can we test invalid usage? Many thanks!
By test invalid usage of parameters, I guess you mean write scenarios with invalid parameters.
For example.
Say that you have a method:
public Integer toInteger(String input){
//conversion logic
}
Now, you would want to know how your method behaves on different scenarios.
One scenario would be passing invalid parameter such as null, and see how your method behaves.
#Test
public void testToIntegerForNullParam(){
myClass.toInteger(null);
}
This method will not pass if you didn't handle null checking, and you will have to refactor to pass this test.
public Integer toInteger(String input){
if(input == null){
throw new IllegalArgumentException("Argument was null!");
}
//conversion logic
}
Then in your test, you can test if this indeed throws exception when argument is null. You can use expected = IllegalArgumentException.class
#Test(expected = IllegalArgumentException.class)
public void testToIntegerForNullParam(){
myClass.toInteger(null);
}
You can continue adding more scenarios such as string not being numeric etc.

code not throwing exception

I am trying to execute below written code and the code should throw an exception but it isn't doint it
try {
Field.class.getMethod("getInt", Object.class).setAccessible(false);
StringSearch.class.getMethod("searchChars",cc.getClass(),pattern3.getClass()).setAccessible(false);
ss4.getClass().getMethod("searchChars",cc.getClass(),pattern3.getClass()).setAccessible(false);
ss4.searchChars(cc,pattern3);
ss4.searchString(str,pattern);
}
catch(NoSuchMethodException ex){
ex.printStackTrace();
}
it should actually throw IllegalAccessException.
ss4 is an object of class BNDMWildcardsCI (one of the algo for String search)
cc, pattern3 are character arrays
str, pattern are Strings
why it isn't throwing an exception, it is not throwing the NoSuchMethodFound exception means that it is able to find the method also i tried to print the isAccessible and it says false
but when i run the tests it doesn't throw any exception
To the best of my knowledge, if a method is declared public (or otherwise accessible), setAccessible(false) can't make it private. It's only useful if you have a private method and you previously called setAccessible(true).
The method setAccessible(boolean) work on object reflect not on normal object. In your code you set it on a method object not on the ss4 object.
To show my point:
Class<?> clazz = ss4.getClass();
Method searchCharsMethod = clazz.getMethod("searchChars",cc.getClass(),pattern3.getClass());
searchCharsMethod.setAccessible(true);
You have set the accessible flag to false on object assigned to searchCharsMethod not ss4.
As bonus see what happen when you call
searchCharsMethod.invoke(ss4,cc,pattern3);
For more please read the documentation

Categories