AssertJ exception handling (feat.assertThat+isInstanceOf) - java

I have been on this problem for hours but couldn't get close to solution.
Any help will be appreciated.
public static int enterTheAmount(){
int final LOTTO_PRICE = 1000;
int amount = Integer.parseInt(Console.readLine());
if(amount%LOTTO_PRICE!=0) throw new IllegalArgumentException();
return amount/LOTTO_PRICE;
}
Here, a user is going to enter a number, and if the number is not divisible by 1000, it throws an exception.
void validateTheEnteredAmount(){
final String INVALID_NUMBER = "1234";
InputStream in = new ByteArrayInputStream(INVALID_NUMBER.getBytes());
System.setIn(in);
assertThat(Application.enterTheAmount()).
isInstanceOf(IllegalArgumentException.class);
}
And I want to know when invalid number is entered, illegalArgumentException is thrown.
I used assertThat method & isInstanceOf methods to validate.
but for some reason, the test keeps failing..
Anyone with clues, please help
i used inputStream to store the number into the scanner.
On the console, it shows that illegalargumentexception is thrown, but the test fails..

You should use assertThrows to check this.
assertThrows(IllegalArgumentException.class, () -> Application.enterTheAmount());
This will assert that the method throws an exception. If it doesn't, the test will be considered as failed.

In the same situation I added a variable with Class type :
private Class exceptionClass;
And I will initialize it in a catch block as below:
public void updateBalance() {
try {
Account account = accountRepository.findById(id).get();
account.setBalance(balance);
accountRepository.save(account);
} catch (Exception e) {
exceptionClass = e.getClass();
}
}
And I wrote a method for my class that will check the result like below:
boolean hasObjectOptimisticLockingFailure() {
return this.exceptionClass == ObjectOptimisticLockingFailureException.class;
}
Then in my test method I checked it with below assertion statement:
assertTrue(account1.hasObjectOptimisticLockingFailure()
|| account2.hasObjectOptimisticLockingFailure());
I think you can do the same for your codes!!

Related

Built-in exception length shorter than expected?

I go over the all build-in exception in JDK, I only find SizeLimitExceededException when size exceed the expected length. However, if I want to throw an exception when size limit is below the expected length, there is no such built-in exception class that I can call?
Update:
SSN is 9 digits length. If input SSN is shorter than 9 digits length, then I want to throw this exception.
While using a fitting exception is good practice and you should spend some time to look for a fitting one (as you did), there is usually also no need to go over board with it.
In your example, I'd consider it totally fine if you'd just throw an new IllegalArgumentException("SSN is only of length <X> but length 9 is required"). It will fail the execution and give you a meaningful stacktrace.
Be aware that it is considered bad practice to use exception for control flow. So please never ever use something like
try {
person.setSSN(ssn);
catch (SSNTooShortException e) {
println("SSN too short! Please try again");
}
Instead use a custom validator to check SSN before setting it and only use the exception to guard against programming error.
if (!SSNFormat.matches(ssn)) { // <-- whoops condition is inverted
person.setSSN(ssn);
}
This snippet will hopefully fail soon in your (unit) test and you will know that your programming logic is flawed.
Of course, depending of your application, instead of using your custom validator, you could and should use one of the many validator frameworks (for an example, look at Hibernate's constraints, but virtually all big frameworks support validation in one or the other form).
Suppose there was a built-in JDK SizeLimitSubceededException (I just learned that subceeded is the opposite of exceeded). Would your code, which checks the length of the SSN throw one exception - SizeLimitExceededException - if the size exceeds the expected size, and another exception - SizeLimitSubceededException - if the size subceeds the expected size?
This would be awkward:
You would have to specify both exceptions in the throws clause of your method (assuming SizeLimitSubceededException would be a checked exception, same as SizeLimitExceededException).
The caller of your method would have to handle both exceptions.
And what if the size is right, but something else is wrong - for example, the SNN contains non-digit characters? Would you throw a third exception for that?
My point is that you'd be better off throwing a single type of exception from the method that sets the SSN.
If you want this to be a checked exception (which I suggest, in order to force the caller to handle it), I suggest defining your own custom exception - perhaps InvalidSSNException. This exception can have a constructor with several arguments - one of them the invalid SSN, another could be a boolean that indicates if the exception was thrown due to incorrect length.
Then your custom exception can produce an error message that matches the reason to the failure:
If the entered SSN had the wrong length (and it doesn't matter if it's too long or too short), the message would specify the expected length (9).
If the entered SSN had the correct length, the message would specify the valid characters (digits only).
Example:
class Person {
...
public setSSN (String ssn) throws InvalidSSNException
{
if (ssn == null) {
throw new InvalidSSNException (ssn, false);
}
if (ssn.length() != 9) {
// exception thrown as a result of invalid length
throw new InvalidSSNException (ssn, true);
}
for (char c : ssn.toCharArray()) {
if (c < '0' || c > '9') {
// exception thrown as a result of invalid character
throw new InvalidSSNException (ssn, false);
}
}
this.ssn = ssn;
}
...
}
Maybe you want something like IndexOutOfBoundsException. It is thrown to indicate that an index of some sort of data is out of range.
https://docs.oracle.com/javase/7/docs/api/java/lang/IndexOutOfBoundsException.html
You can create an exception as
public class UnderBottomException extends Exception {
public UnderBottomException(int dim, int param) {
super();
System.out.println("you entered a length of : " + dim + " whereas the minimum length expected is : " + param);
}
}
This exception will be implementable this way in your POJO :
public class Register {
private int[] registre;
private int minRange = 9;
public Register(int[] parametre) throws UnderBottomException {
if (parametre.length < this.minRange) {
throw new UnderBottomException(parametre.length, this.minRange);
}
else {
this.registre = new int[parametre.length];
for (int i = 0 ; i < this.registre.length; i++)
this.registre[i] = parametre[i];
}
}
public int[] getRegistre() {
return registre;
}
public int getMinRange() {
return minRange;
}
}
And finaly you use your object catching exception like this :
public class Main {
public static void main(String[] args) {
int[] a = {1,2,3,4,5,6,7,8};
try {
Register monRegistre = new Register(a);
System.out.println("Nickel le sous registre de rang 2 = " + monRegistre.getRegistre()[1]);
}
catch(UnderBottomException e) {
}
}
}
Output :
you entered a length of : 8 whereas the minimum length expected is : 9

Java recursion and exceptions

I currently did my programming assignment which was said to use recursion to find the factorial of a number that the user inputs. I successfully did it and it worked, but I decided to expand the code a bit and add an exceptions for kicks.
Basically I want the program to prompt the user to enter a number greater than or equal to 0 and if the user enters a number that is less than 0 I want an exception to be thrown, caught and handled. I know in this code I'm using the incorrect exception which is StringTooLong, but I don't know any other exceptions off the top of my head. By the way when I run my code I get an error of cannot find symbol at the throw lengthException.
Here's my code:
import java.util.Scanner;
public class Recursion {
public static void main(String args[]) {
long userNum;
System.out.println("Enter a number to check it's factorial");
Scanner scnr = new Scanner(System.in);
userNum = scnr.nextLong();
StringTooLongException lengthException =
new StringTooLongException ("String has too many characters");
System.out.println(fact(userNum));
}
public static long fact(long userNum) {
try {
if(userNum < 0) {
throw lengthException;
} else if(userNum == 1 || userNum == 0) {
return 1;
} else {
return userNum*fact(userNum-1);
}
} catch(Exception e) {
System.out.println("Enter a number that is greater or equal to 0," + e);
}
}
}
Try:
throw new StringTooLongException();
And you can remove the following:
StringTooLongException lengthException =
new StringTooLongException ("String has too many characters");
Though as #KevinO and the others have suggested, it is more suitable to be using IllegalArgumentException, e.g.
throw new IllegalArgumentException();
Or, you could create your own custom Exception, e.g.
public class InvalidInputException extends Exception {
public InvalidInputException(String message) {
super(message);
}
}
You have declared lengthException in main, and tried to use it in fact. It is hence out of scope for the method fact(long userNum). Thus the error you got.
You can take a look at this for more on exceptions.
You could use NumberFormatException:
...
if(userNum <= 0)
{
throw new NumberFormatException("Must be a positive integer");
}
...
} catch (NumberFormatException e) {
System.err.println("Enter a number that is greater or equal to 0," + e);
}
You need to use new to fix your throw lengthException error. Also I think you meant to use 'throw new StringTooLongException();'
You should also learn more about what an exception is and what it is used for. One thing is that an Exception is actually a class, and any subclass of the Exception class is itself an Exception. So, if you wanted, you could create your own exception by simply extending the Exception class. This is why you must use the new keyword when throwing the exception: you are throwing a new instance of an Exception (or one of its subclasses).
You can see a list of some top-level exceptions by exploring the direct known subclasses section in the JavaDoc for the Exception class.
A clean alternative for your implementation is to create your own custom Exception which fits your requirements.
For example, you can create a custom exception class as follows:
public class InvalidInputException() extends Exception
{
public InvalidInputException()
{
super();
}
public InvalidInputException(String message)
{
super(message);
}
}
This implementation would allow you to throw new InvalidInputException() in your try-catch block, and is more informative to the user.

How to determine the origin of a thrown exception without writing a try/catch for each statement?

I am wondering if this is possible to do without writing a try/catch block for every single call. I want to be able to tell which method threw the exception so I can handle them differently. Consider the following two (fairly identical) methods:
public void setBranchID(String ID) throws NumberFormatException{
if(ID.trim().length() != 0 && ID != null){
try{
branchID = Integer.parseInt(ID);
}catch(NumberFormatException ex){
OutputFunc.printError(ex); //Prints the stack trace to console
throw ex;
}
}
else{
branchID = null;
}
}
public void setCashOnHand(String cash) throws NumberFormatException{
if(cash.trim().length() != 0 && cash != null){
try{
cashOnHand = Double.parseDouble(cash);
}catch(NumberFormatException ex){
OutputFunc.printError(ex);
throw ex;
}
}
else{
cashOnHand = null;
}
}
What I want to do:
try{
setBranchID(String1);
setCashOnHand(String2);
//Other methods
}catch(NumberFormatException ex){
if(/*Exception came from setBranchID*/){
//Code
}
else if(/*Exception came from setCashOnHand*/){
//Code
}
}
You'll need to create a custom exception, which would have some sort of enumeration which would provide hints as to where the error took place:
public enum ErrorType {
BranchId,
CashOnHands
}
public class MyException extends Exception {
private ErrorType errorType;
public MyMyException(string message, ErrorType errorType) : super(message) {
this.errorType = errorType;
}
public ErrorType getErrorType() {
return this.errorType;
}
}
Then you create an exception like so: throw new MyException(..., ErrorType.Branch) and then, in your handling statement:
...
catch(MyException e) {
switch(e.getErrorType) {
case ErrorType.BranchId:...
}
}
you do not necessarily need to create a new exception (even though its probably nicer) but you can just change the message returns from the exception :
public void setBranchID(String ID) throws NumberFormatException{
if(ID.trim().length() != 0 && ID != null){
try{
branchID = Integer.parseInt(ID);
}catch(NumberFormatException ex){
OutputFunc.printError(ex); //Prints the stack trace to console
throw new NumberFormatException("setBranchID error : " + ex );
}
}
else{
branchID = null;
}
}
Then you can get the exception message if it starts with the setBranchId:
try{
t.setBranchID("xxx");
t.setCashOnHand("xxx");
//Other methods
} catch (NumberFormatException ex){
if (ex.getMessage().startsWith("setBranchID")) {
System.out.println("error from setBranchID method");
}
.....
}
You can also try something like this---
try {
setBranchID(String1);
setCashOnHand(String2);
} catch (Exception e) {
StackTraceElement se[] = e.getStackTrace();
String s = se[0].toString();
int startIndex = s.indexOf(".");
int endIndex = s.indexOf("(");
String newstr = s.substring(startIndex + 1, endIndex);
}
newstr will have the name of the function that throws the exception. You can compare it and do your desired processing.
I tried it and its working fine.
I hope it would help you.
You can avoid to write a try - catch block for every single method simply obtaining the method name directly from the stack trace like this:
public class TestClass {
public void testMethod1(){
int x = 1/0;
}
public void testMethod2(){
int x = 1/0;
}
public static void main(String[] args) {
TestClass c = new TestClass();
try {
c.testMethod2();
} catch (Exception e){
System.out.println(e.getStackTrace()[0].getMethodName());
}
}
}
The main method above prints testMethod2
The answer to your question is quite simple, don’t re-throw and exception. But maybe you want to do this, so then probably your custom exception is the easiest way because you can enforce that it has the information about the original method. But can I just make some remarks, don’t read if not interested but please consider.
This code you have written looks very similar to the code I wrote when I first started doing GUI programming, I thought using this functionality from checked exceptions is a good idea for validating user input but it’s not. I even stuck checked exceptions in the data objects themselves, for instance in the setters of an employee class.
Eventually what you’ll find that methods, which have nothing to do with exceptions generated by methods nested deep in your control structure are having to handle exceptions or throw an exception which has nothing to do with them, soon every method in your code will be doing this, for many different exceptions.
What is the answer then? You’ll find that preventing exceptions will be your best attack. Use components which enforce the correct data, such as formatted text fields. Then in your code you can know with certainty that methods are not going to have exceptions. If you have complex validation going on, then just think about how you can design your code, look at some GUI patterns such as the MVC pattern (there are at least 2 versions of this pattern by the way). Then there are alternatives, I found returning an enumeration value then using a switch statement for each case can be a nice solution too. Or another idea is that each error message you can merely append to a string and then output as well, anything but throwing exceptions, and if you are going to throw an exception, don’t throw a checked one unless someone is going to die if you don’t.
I think it’s a fine art to know when it is a good idea to throw an exception, but shouldn’t be your first choice.

Throw an exception when too many/few arguments are passed to main

I'm writing a dice rolling programme which has two parameters passed to the main, how many sides the dice has and the amount of times you want to throw it. I wanted to throw an exception if less than or more than two parameters are passed. How would I go about doing this?
I found this.
But I'm not really sure how to use it? Surely I must somehow specify the amount of arguments that are expected before that exception can be thrown?
Try this :
public class Dice {
public static void main(String... args) {
// First, ensure there are 2 args
if (args.length != 2) {
throw new IllegalArgumentException("Exactly 2 parameters required !");
}
int firstArgInt;
int secondArgInt;
// Verify all args are integers
try {
firstArg = Integer.parseIng(args[0]);
} catch (NumberFormatException nbfe) {
// 2 possible solutions : throw an exception, or assign a default value
// - throw new IllegalArgumentException("First arg must be an integer");
// - firstArg = 42;
}
try {
secondArg = Integer.parseIng(args[1]);
} catch (NumberFormatException nbfe) {
// Same as above
}
// Etc.
}
}

Validation Method that calls itself in java

I trying to understand why the method validateItemquantity eventually crashes with an NumberFormatException error. The logic seem correct, but something is not right. Its suppose to keep asking the user to reenter until it gets an valid input and then return that valid input.
String validateItemquantity(String itemQuantity) {
try{
Integer.parseInt(itemQuantity);
}
catch (NumberFormatException e) {
itemQuantity = JOptionPane.showInputDialog
("Invalid item quantiy, please enter a new Value");
validateItemquantity(itemQuantity);
}
return itemQuantity ;
Method that calls it:
private void bnPurchaseActionPerformed(java.awt.event.ActionEvent evt) {
String itemCode, validItemquantity ;
int itemQuantity, itemPrice, itemCost, totalCost ;
validItemquantity = validateItemquantity(itemQuantityinput.getText());
itemQuantity = Integer.parseInt(validItemquantity);
itemCode = itemCodeinput.getText();
itemPrice = catalog.searchCatalog(itemCode);
itemCost = payment.calculateItemcost(itemQuantity,itemPrice);
totalCost = payment.calculateTotalcost(itemCost);
Have it return the result of the parse or call itself on exception, like this:
String validateItemQuantity(String itemQuantity) {
try {
return Integer.parseInt(itemQuantity); // returns if no exception
} catch (NumberFormatException e) {
return validateItemQuantity(JOptionPane.showInputDialog
("Invalid item quantiy, please enter a new Value"));
}
}
This method will only return a valid response; it loops forever until it gets a valid response.
A few comments have mentioned that the above code may be attacked by the user entering bad data millions of times and blowing the stack. I say "let them", but if you really want to make it safe, use a while loop:
String validateItemQuantity(String itemQuantity) {
while (true) {
try {
return Integer.parseInt(itemQuantity); // returns if no exception
} catch (NumberFormatException e) {
itemQuantity = JOptionPane.showInputDialog(
"Invalid item quantiy, please enter a new Value"));
}
}
}
It adds a while loop, so the code complexity increases slightly, but it's only couple of extra lines of code and it is more efficient and safe.
I trying to understand why the method validateItemquantity eventually crashes with an NumberFormatException error.
You need to post the stack-trace for investigating. Better yet, use a debugger to see where you get the exception.
The logic seem correct
It seems correct, but convoluted :) Is there a reason you have to use recursion? How about something simple like this?
String validateItemquantity(String itemQuantity) {
while (true) {
try {
Integer.parseInt(itemQuantity);
return itemQuantity;
}
catch (NumberFormatException e) {
validateItemquantity(itemQuantity);
}
itemQuantity = JOptionPane.showInputDialog
("Invalid item quantity, please enter a new Value");
}
}
The problem is that you're changing references. itemQuantity is assigned a different reference within each "catch" block. That change of reference does not update the parameter passed into the function. It's basically a "pass-by-value" error.
Your method validateItemQuantity returns either the original string that was passed in (if valid), or the string acquired by the first showing of the input box from the catch-block (unconditionally). All the recursive calls and all their input boxes are wasted.

Categories