Apache Commons Validator and JUnit - java

I'm using Apache Commons Validator to validate input within a builder pattern.
Once build() is called on the builder, the variables are checked using methods such as:
Validate.notNull(oranges, "Oranges was not set.");
When testing my code, I can see that when I do not set oranges, I do indeed get the message "Oranges was not set". However, the exception that is thrown is still a NullPointerException.
In my unit tests, I want to check that the validator is used and a message is output, but clearly using:
#Test(expected = NullPointerException.class)
will pass regardless of whether the Validator is used or a message is set.
Is there a way I can check that the validator is used and the message is set in JUnit? If not, is there a library that will allow me to do this?

You should only check the external behaviour of your code. In your case this is: it throws a NullPointerException with the appropriate message.
There are different ways for testing exceptions (see JUnit Wiki). You can always use JUnit's ExpectedException rule
public class YourTest {
#Rule
public final ExpectedException thrown = ExpectedException.none();
#Test
public void test() {
...
thrown.expect(NullPointerException.class);
thrown.expectMessage("Oranges was not set.");
builder.build();
}
}
With Java 8 you can use the method exceptionThrownBy provided by the library Fishbowl. It allows you to use Arrange-Act-Assert pattern.
public class YourTest {
#Test
public void test() {
...
Throwable exception = exceptionThrownBy(() -> builder.build());
assertEquals(NullPointerException.class, exception.getClass());
assertEquals("Oranges was not set.", exception.getMessage());
}
}

Related

How to test for Exception in #Async method?

How can I assert that a certain exception is thrown inside an #Async method?
Because the following exception is caught by Springs SimpleAsyncUncaughtExceptionHandler.
#Service
public class Service {
#Async
public void run() {
throw new RuntimeException();
}
}
public class Test {
#Test
public void test() {
assertDoesNotThrow(() -> service.run()); //this always passes
}
}
If it is possible for your case, separate testing of asynchronicity and the actual unit of work. E.g. write test that will execute (no 'Async' functionality) Service.run() and assert that no/any/some exceptions are thrown.
In second test (utilizing #Async execution) you could test for the actual unit of work i.e. use your Spring provided bean and test for e.g.:
Awaitility.await().atMost(1000, TimeUnit.MILLISECONDS).untilAsserted(() -> runAnyCodeThatChecksTheResultOfYourServiceRunMethod());
Another method might be to replace the return type of the Service.run() method to java.util.concurrent.Future, Spring will then re-throw the exception. From AsyncExecutionAspectSupport.handleError javadoc:
"If the return type of the method is a {#link Future} object (again, if applicable), the original exception can be propagated by just throwing it at the higher level. However, for all other cases, the exception will not be transmitted back to the client."
import static org.awaitility.Awaitility.await;
Awaitility.await().atMost(5, TimeUnit.SECONDS)
.untilAsserted(() -> assertThrows(RuntimeException.class, () -> service.run()));

How to assert that void method throws Exception using Mockito and catch-exception?

I'm trying to test this method:
public void deleteCurrentlyLoggedInUser(Principal principal) {
if (findLoggedInUser(principal) == null) {
throw new UserAlreadyDeletedException();
}
userRepository.delete(findLoggedInUser(principal));
}
Here is findLoggedInUser:
User findLoggedInUser(Principal principal) {
return userRepository.findByUsername(principal.getName());
}
And here is my test so far:
#Test
public void shouldThrowExceptionWhenUserNotFound() {
// given
when(sut.findLoggedInUser(principalStub)).thenReturn(null);
// when
sut.deleteCurrentlyLoggedInUser(principalStub);
// then
catchException
verify(userRepositoryMock, never()).delete(any(User.class));
}
So how do I catch exception using catch-exception here? Method that I'm testing returns void and I just can't seem to find a way to assert that exception was found.
EDIT: I know I could use: #Test(expected = UserAlreadyDeletedException.class) but I want to switch my whole project to catch-exception because it's much better and using expected in #Test is not very reasonable.
I've never heard of catch-exception, but it doesn't exactly seem like an up-to-date library: the last update to the main source code (at the time of writing) was on May 3 2015.
If you're using Java 8, and can use JUnit 4.13 or later, you can use assertThrows:
assertThrows(
UserAlreadyDeletedException.class,
() -> sut.deleteCurrentlyLoggedInUser(principalStub));
If you're going to migrate all of your code to something, this seems like a better long-term bet.
It might be that using Rules is something that could work for you?
Rules allow very flexible addition or redefinition of the behavior of each test method in a test class. Testers can reuse or extend one of the provided Rules below, or write their own.
You can read more about this neat feature of junit4 here:
https://github.com/junit-team/junit4/wiki/Rules
Example:
public static class HasExpectedException {
#Rule
public final ExpectedException thrown = ExpectedException.none();
#Test
public void throwsNullPointerException() {
thrown.expect(NullPointerException.class);
throw new NullPointerException();
}
}

Why my JUnit error collector is not reporting the error?

I am trying to report error using JUnit error collector. Although my assertion is failing, error is not reported in JUnit. But I am getting the "error" message in console.
#Rule
public ErrorCollector errcol = new ErrorCollector();
#Then("^Business alert message on the screen$")
public void Business_alert_message_on_the_screen(Result_Update) throws Throwable {
if (userType.equals("Admin")) {
try {
Assert.assertEquals("Update button is not present for the admin user", true, Result_Update);
} catch (Throwable t) {
errcol.addError(t);
System.out.println("Error");
}
}
}
tl;dr : Make sure your test class doesn't extend TestCase.
I had a similar problem when I was using JUnit 4 with IntelliJ IDEA. I naïvely selected a base class of TestCase in the dialog, which was the default for JUnit 3, because I figured "it'd be nice to have those handy this#assert* methods" (the default for JUnit 4 is null). The bad code (which didn't work) is below:
public class SassCompilerTest extends TestCase {
#Rule
public ErrorCollector collector = new ErrorCollector();
#Test
public void testCompiler() throws IOException {
collector.checkThat(true, CoreMatchers.equalTo(false));
}
}
However, in JUnit 4, that prevented a lot of features from working. Removing the parent class fixed the test:
public class SassCompilerTest {
#Rule
public ErrorCollector collector = new ErrorCollector();
#Test
public void testCompiler() throws IOException {
collector.checkThat(true, CoreMatchers.equalTo(false));
}
}
The solution was suggested to me by a comment in the issue with Cucumber mentioned by #StefanBirkner in another answer. After reading that, I tried extending ErrorCollector to make the ErrorCollector#verify public and call it from an #After method, but the #After method wasn't getting called, which made me realize something was either wrong with the TestRunner (which was IntelliJ's default) or the Test itself.
According to JUnit:
The ErrorCollector rule allows execution of a test to continue after
the first problem is found
errcol.addError(t);//only adds the error to the ErrorCollector
This means that the test continues after collecting the error.
You should add:
errcol.checkThat(...); //will pass/fail the test
See examples:
https://junit.org/junit4/javadoc/4.12/org/junit/rules/ErrorCollector.html (Updated)
https://gist.github.com/cb372/2419626
The Cucumber runner does not support #Rule because it extends ParentRunner and not BlockJUnit4ClassRunner (see source code of the runner). There is already an issue for supporting ErrorCollector.

Unit testing that log message written when exception caught

Here is the code that I am working with. In this test I want to verify that the log method is being called when an exception is caught.
public class SuperClass(){
public void log()
{
do some logging;
}
}
public class ClassUnderTest extends SuperClass(){
public String methodbeingtested(Object param)
{
try
{
String a = SomeObject.
methodthatthrowsexception(param);//static method, throws JAXB/NPE
}
catch(Exception exp)
{
log("log msg",exp);//inherited method
}
}
}
public class ClassUnderTestTest {
#Test
public testmethodbeingtested(){
ClassUnderTest cut = new ClassUnderTest()
ClassUnderTest cutspy = Mockito.spy(cut);
cutspy.methodbeingtested(param);
Mockito.verify(cutspy).log("log msg", new Exception()); // exp is needed to here.
}
}
After looking at several samples, the above was the closest I could get. This testcase forces an exception. But it fails to verify the log method call as Mockito.verify requires the exact exception (exp) that is caught, which the test case does not have access to.
Is there any other way to test this scenario?
Mockito's verify method can be used with argument matchers. If you want to verify that log was called, with any Exception at all as the second argument, you can just write
verify(cutspy).log(eq("log msg"), any(Exception.class));
I've assumed that you have the right static imports for verify, eq and any.
As an aside, this test does not need PowerMock. Your line PowerMock.expectLastCall().once(); is both redundant and confusing, and should probably be removed, along with the #PrepareForTest annotation.
Instead of spying on ClassUnderTest, you should mock the logging framework, inject it into the class and then verify that the log method gets called. Id' also mock the SomeObject class and have it throw exception.
As an aside, you should really evaluate if you need to verify your log statements. Perhaps you have a valid reason to do so but typically, asserting/verifying to this extent is not required and will only make your tests brittle.

Java JUnit test case with exceptions

what's wrong with this. I have junit 4
You can declare on the #Test annotation that, for the test to pass, it must throw these exceptions:
#Test(expected = NullPointerException.class)
public void testSynapseOne() {
// test
}
#Test(expected = IllegalStateException.class)
public void testSynapseTwo() {
// test
}
Of course, you have to be sure you're testing the right thing - currently, your tests don't make use of the constructor, which is the critical piece you want to test.
Oh - you don't want to have your tests extend TestCase unless you need compatibility with JUnit3.x.
You can use the annotation #Test(expected = TheClassException.class) to write a test which is supposed to throws the exception of class TheClassException

Categories

Resources