I am writing a test case for my class that has methods which throw exceptions (both checked and runtime). I have tried different possible ways of testing as suggested in this link.. It appears they seem to work only for runtime exceptions. for Checked exceptions, I need to do a try/catch/assert as shown in the code below. Is there any alternatives to try/catch/assert/. you will notice that testmethod2() and testmethod2_1() shows compile error but testmethod2_2() does not show compile error which uses try/catch.
class MyException extends Exception {
public MyException(String message){
super(message);
}
}
public class UsualStuff {
public void method1(int i) throws IllegalArgumentException{
if (i<0)
throw new IllegalArgumentException("value cannot be negative");
System.out.println("The positive value is " + i );
}
public void method2(int i) throws MyException {
if (i<10)
throw new MyException("value is less than 10");
System.out.println("The value is "+ i);
}
}
Test class:
import static org.junit.Assert.*;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
public class UsualStuffTest {
private UsualStuff u;
#Before
public void setUp() throws Exception {
u = new UsualStuff();
}
#Rule
public ExpectedException exception = ExpectedException.none();
#Test(expected = IllegalArgumentException.class)
public void testMethod1() {
u.method1(-1);
}
#Test(expected = MyException.class)
public void testMethod2() {
u.method2(9);
}
#Test
public void testMethod2_1(){
exception.expect(MyException.class);
u.method2(3);
}
public void testMethod2_3(){
try {
u.method2(5);
} catch (MyException e) {
assertEquals(e.getMessage(), "value is less than 10") ;
}
}
}
#Test(expected = MyException.class)
public void testMethod2() throws MyException {
u.method2(9);
}
Related
I wrote this service
public class FirstService {
private final SecondService secondService;
public FirstService(SecondService secondService) {
this.secondService = secondService;
}
public void hz() throws Exception {
try {
methodThrowsException();
} catch (Exception e){
secondService.handleErrorMessage(e.getMessage());
throw e;
}
}
private void methodThrowsException() throws Exception {
throw new Exception("message");
}
}
And this service:
public class SecondService {
public void handleErrorMessage(String message) {}
}
I need to verify that handleErrorMessage was called. I wrote a test:
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import static org.junit.Assert.*;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
public class FirstServiceTest {
private FirstService firstService;
private SecondService secondService;
#Before
public void setUp() {
secondService = mock(SecondService.class);
firstService = new FirstService(secondService);
}
#Test(expected = Exception.class)
public void hz() throws Exception {
firstService.hz();
ArgumentCaptor<String> argumentCaptor = ArgumentCaptor.forClass(String.class);
verify(secondService).handleErrorMessage(argumentCaptor.capture());
String value = argumentCaptor.getValue();
assertEquals("message", value);
}
}
Test pass. But if I change assertEquals("message666", value); it still pass. If I don't throw an exception in catch block - ArgumentCaptor captures argument, but when I throw an exception it doesn't work.
Your test is annotated:
#Test(expected = Exception.class)
This means that the test will pass if an Exception (or any subclass of) makes it up to the top level. This happens on the first line of your test:
firstService.hz();
This is why it passes. Unfortunately, that exception means that the rest of your test is never run, since that exception propagates up and out of your test method.
A bit ugly, but this snippet does what you want:
#Test
public void hz() throws Exception {
try {
firstService.hz();
// If we get here, then we didn't throw an exception - fail
Assert.fail();
} catch (Exception ex) {
// Exception was expected - disregard and continue
// no-op
}
ArgumentCaptor<String> argumentCaptor = ArgumentCaptor.forClass(String.class);
verify(secondService).handleErrorMessage(argumentCaptor.capture());
String value = argumentCaptor.getValue();
assertEquals("message", value);
}
The above runs your method, and catches the exception (and fails if you didn't get the expected exception). Then, it proceeds, and runs the rest of your test.
JUnit 5 provides a slightly cleaner way, but you'd have to migrate:
#Test
public void hz() throws Exception {
Assertions.assertThrows(Exception.class, () -> firstService.hz());
ArgumentCaptor<String> argumentCaptor = ArgumentCaptor.forClass(String.class);
verify(secondService).handleErrorMessage(argumentCaptor.capture());
String value = argumentCaptor.getValue();
assertEquals("asdf", value);
}
With JUnit4 you could e.g. just write:
#Test (expectedException = new UnsupportedOperationException()){...}
How is this possible in JUnit5? I tried this way, but I'm not sure if this is equal.
#Test
public void testExpectedException() {
Assertions.assertThrows(UnsupportedOperationException.class, () -> {
Integer.parseInt("One");});
Yes, those are equivalent.
public class DontCallAddClass {
public void add() {
throws UnsupportedOperationException("You are not supposed to call me!");
}
}
public class DontCallAddClassTest {
private DontCallAddClass dontCallAdd = new DontCallAddClass();
#Rule
public ExpectedException exception = ExpectedException.none();
#Test
public void add_throwsException() {
exception.expect(UnsupportedOperationException.class);
dontCallAdd.add();
}
#Test(expected = UnsupportedOperationException.class)
public void add_throwsException_differentWay() {
dontCallAdd.add();
}
#Test
public void add_throwsException() {
Assertions.assertThrows(UnsupportedOperationException.class, dontCallAdd.add());
}
}
The three test methods above are quivalent. In Junit 5 use the last one. It's the newer approach. It also allows you to take advantage of Java 8 lambdas. You can also checks for what the error message should be. See below:
public class DontCallAddClass {
public void add() {
throws UnsupportedOperationException("You are not supposed to call me!");
}
}
public class DontCallAddClassTest {
private DontCallAddClass dontCallAdd = new DontCallAddClass();
#Rule
public ExpectedException exception = ExpectedException.none();
#Test
public void add_throwsException() {
exception.expect(UnsupportedOperationException.class);
exception.expectMessage("You are not supposed to call me!");
dontCallAdd.add();
}
// this one doesn't check for error message :(
#Test(expected = UnsupportedOperationException.class)
public void add_throwsException_differentWay() {
dontCallAdd.add();
}
#Test
public void add_throwsException() {
Assertions.assertThrows(UnsupportedOperationException.class, dontCallAdd.add(), "You are not supposed to call me!");
}
}
check there for more information: JUnit 5: How to assert an exception is thrown?
Hope this clear it up
I am getting an exception when I run my JUnit tests.
java.lang.Exception: Test class should have exactly one public constructor
Below is my code snippet, any ideas?
package com.tests;
import org.junit.Rule;
import org.junit.rules.TestRule;
import org.junit.runner.Description;
import org.junit.runners.model.Statement;
public class AllTests implements TestRule {
private int retryCount;
private AllTests(int retryCount) {
this.retryCount = retryCount;
}
public Statement apply(Statement base, Description description) {
return statement(base, description);
}
private Statement statement(final Statement base, final Description description) {
return new Statement() {
#Override
public void evaluate() throws Throwable {
Throwable caughtThrowable = null;
// implement retry logic here
for (int i = 0; i < retryCount; i++) {
try {
base.evaluate();
return;
}
catch (Throwable t) {
caughtThrowable = t;
System.err.println(description.getDisplayName() + ": run " + (i + 1) + " failed");
}
}
System.err.println(description.getDisplayName() + ": giving up after " + retryCount + " failures");
throw caughtThrowable;
}
};
}
#Rule
public AllTests allTests = new AllTests(3);
#ClassRule
public static DockerComposeRule docker = wi.getDocker(logs);
#Override
public DockerComposeRule getDocker() {
return docker;
}
#Test
public void myFirstTest() throws Exception {
// Test code here...
}
}
I am running a JUnit test, with Gradle. It is a Java project and it fails straightaway.
I have tried numerous things but to no avail. Happy to provide more details if you want.
The message is clear :
java.lang.Exception: Test class should have exactly one public
constructor
You merged the unit test class with the Rule test class in the same class : AllTests.
You should define your rule in its own class and remove this constructor :
private AllTests(int retryCount) {
this.retryCount = retryCount;
}
I want my unit test classes to check for the error code (which is a custom property of my exception class) and assert when an exception is thrown from the tested code. Can I do this using testng.
I have the following exception class :
public final class CustomException extends Exception {
public CustomException(String msg,String errorCode,Throwable cause) {
super(msg,cause);
this.errorCode = errorCode;
}
private String errorCode;
public String getErrorCode() {
return this.errorCode;
}
}
My Unit Test Class :
import org.testng.annotations.Test;
public class MyUnitTestClass {
#Test(priority = 25,
expectedExceptions = CustomException.class,
expectedExceptionsMessageRegExp = "Error while doing something.")
public void testDoSomething() {
// code to invoke doSomething();
// which throws CustomException on some exception.
}
}
Instead of expectedExceptionsMessageRegExp="Error while doing something." i want to assert on an error code Eg: like "ERR100909" which will be set in the errorCode property of CustomException class.
Unit Test Framework : Testng
Version : 6.9.4
Thanks!
One of the ways in which you can do this is by implementing IHookable interface. Here's a sample that shows this in action.
import org.testng.IHookCallBack;
import org.testng.IHookable;
import org.testng.ITestResult;
import org.testng.annotations.Test;
import java.util.Arrays;
import java.util.List;
public class MyUnitTestClass implements IHookable {
private List<String> errorCodes = Arrays.asList("ERR100909", "ERR100");
#Override
public void run(IHookCallBack callBack, ITestResult testResult) {
callBack.runTestMethod(testResult);
Throwable t = testResult.getThrowable();
if (t != null) {
t = t.getCause();
}
boolean shouldFail = (t instanceof CustomException && errorCodes.contains(((CustomException) t).getErrorCode()));
if (!shouldFail) {
testResult.setThrowable(null);
testResult.setStatus(ITestResult.SUCCESS);
}
}
#Test
public void test1() throws CustomException {
throw new CustomException("test", "ERR100", new Throwable());
}
#Test
public void test2() throws CustomException {
throw new CustomException("test", "ERR500", new Throwable());
}
}
I would have assumed that the following test should pass, but the exception is never thrown. Any clues ?
#RunWith(PowerMockRunner.class)
#PrepareForTest(StaticService.class)
public class TestStuff {
#Test(expected = IllegalArgumentException.class)
public void testMockStatic() throws Exception {
mockStatic(StaticService.class);
doThrow(new IllegalArgumentException("Mockerror")).when(StaticService.say("hello"));
verifyStatic();
StaticService.say("hello");
}
}
It's because you are using the doThrow...when syntax incorrectly for static methods. There are a couple different ways to approach this which I've outlined in two separate test methods below.
#RunWith(PowerMockRunner.class)
#PrepareForTest({StaticService.class})
public class StaticServiceTest {
#Test (expected = IllegalArgumentException.class)
public void testMockStatic1() throws Exception {
String sayString = "hello";
mockStatic(StaticService.class);
doThrow(new IllegalArgumentException("Mockerror")).when(
StaticService.class, "say", Matchers.eq(sayString));
StaticService.say(sayString);
fail("Expected exception not thrown.");
}
#Test (expected = IllegalArgumentException.class)
public void testMockStatic2() throws Exception {
String sayString = "hello";
mockStatic(StaticService.class);
doThrow(new IllegalArgumentException("Mockerror")).when(
StaticService.class);
StaticService.say(Matchers.eq(sayString)); //Using the Matchers.eq() is
//optional in this case.
//Do NOT use verifyStatic() here. The method hasn't actually been
//invoked yet; you've only established the mock behavior. You shouldn't
//need to "verify" in this case anyway.
StaticService.say(sayString);
fail("Expected exception not thrown.");
}
}
For reference, here was the StaticService implementation I created. I don't know if it matches yours but I did verify that the tests pass.
public class StaticService {
public static void say(String arg) {
System.out.println("Say: " + arg);
}
}
See Also
http://static.javadoc.io/org.powermock/powermock-api-mockito/1.6.5/org/powermock/api/mockito/expectation/PowerMockitoStubber.html
https://github.com/jayway/powermock/wiki/MockitoUsage#how-to-stub-void-static-method-to-throw-exception
StaticServiceTest.java with imports:
import static org.junit.Assert.fail;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Matchers;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
#RunWith(PowerMockRunner.class)
#PrepareForTest({ StaticService.class })
public class StaticServiceTest {
#Test(expected = IllegalArgumentException.class)
public void testMockStatic1() throws Exception {
/* Setup */
String sayString = "hello";
PowerMockito.mockStatic(StaticService.class);
/* Mocks */
PowerMockito.doThrow(new IllegalArgumentException("Mockerror")).when(
StaticService.class, "say", Matchers.eq(sayString));
/* Test */
StaticService.say(sayString);
/* Asserts */
fail("Expected exception not thrown.");
}
#Test(expected = IllegalArgumentException.class)
public void testMockStatic2() throws Exception {
/* Setup */
String sayString = "hello";
PowerMockito.mockStatic(StaticService.class);
/* Mocks */
PowerMockito.doThrow(new IllegalArgumentException("Mockerror")).when(
StaticService.class);
StaticService.say(Matchers.eq(sayString));
/* Test */
StaticService.say(sayString);
/* Asserts */
fail("Expected exception not thrown.");
}
}
StaticService.java
public class StaticService {
public static void say(String arg) {
System.out.println("Say: " + arg);
}
}
Tests pass fine: