junit testing - assertEquals for exception - java

How can I use assertEquals to see if the exception message is correct?
The test passes but I don't know if it hits the correct error or not.
The test I am running.
#Test
public void testTC3()
{
try {
assertEquals("Legal Values: Package Type must be P or R", Shipping.shippingCost('P', -5));
}
catch (Exception e) {
}
}
The method being tested.
public static int shippingCost(char packageType, int weight) throws Exception
{
String e1 = "Legal Values: Package Type must be P or R";
String e2 = "Legal Values: Weight < 0";
int cost = 0;
if((packageType != 'P')&&(packageType != 'R'))
{
throw new Exception(e1);
}
if(weight < 0)
{
throw new Exception(e2);
}
if(packageType == 'P')
{
cost += 10;
}
if(weight <= 25)
{
cost += 10;
}
else
{
cost += 25;
}
return cost;
}
}
Thanks for the help.

try {
assertEquals("Legal Values: Package Type must be P or R", Shipping.shippingCost('P', -5));
Assert.fail( "Should have thrown an exception" );
}
catch (Exception e) {
String expectedMessage = "this is the message I expect to get";
Assert.assertEquals( "Exception message must be correct", expectedMessage, e.getMessage() );
}

The assertEquals in your example would be comparing the return value of the method call to the expected value, which isn't what you want, and of course there isn't going to be a return value if the expected exception occurs. Move the assertEquals to the catch block:
#Test
public void testTC3()
{
try {
Shipping.shippingCost('P', -5);
fail(); // if we got here, no exception was thrown, which is bad
}
catch (Exception e) {
final String expected = "Legal Values: Package Type must be P or R";
assertEquals( expected, e.getMessage());
}
}

Works perfectly for me.
try{
assertEquals("text", driver.findElement(By.cssSelector("html element")).getText());
}catch(ComparisonFailure e){
System.err.println("assertequals fail");
}
if assertEquals fails ComparisonFailure will handle it

Java 8 solution
Here is a utility function that I wrote:
public final <T extends Throwable> T expectException( Class<T> exceptionClass, Runnable runnable )
{
try
{
runnable.run();
}
catch( Throwable throwable )
{
if( throwable instanceof AssertionError && throwable.getCause() != null )
throwable = throwable.getCause(); //allows "assert x != null : new IllegalArgumentException();"
assert exceptionClass.isInstance( throwable ) : throwable; //exception of the wrong kind was thrown.
assert throwable.getClass() == exceptionClass : throwable; //exception thrown was a subclass, but not the exact class, expected.
#SuppressWarnings( "unchecked" )
T result = (T)throwable;
return result;
}
assert false; //expected exception was not thrown.
return null; //to keep the compiler happy.
}
(taken from my blog)
Use it as follows:
#Test
public void testThrows()
{
RuntimeException e = expectException( RuntimeException.class, () ->
{
throw new RuntimeException( "fail!" );
} );
assert e.getMessage().equals( "fail!" );
}
Also, if you would like to read some reasons why you should not want to assertTrue that the message of your exception is equal to a particular value, see this: https://softwareengineering.stackexchange.com/a/278958/41811

This is nice library that allows asserting exceptions in a clean way.
Example:
// given: an empty list
List myList = new ArrayList();
// when: we try to get the first element of the list
when(myList).get(1);
// then: we expect an IndexOutOfBoundsException
then(caughtException())
.isInstanceOf(IndexOutOfBoundsException.class)
.hasMessage("Index: 1, Size: 0")
.hasNoCause();

Related

Spring Boot: #Transactional rollbackFor checked Exception

I am trying to achieve transactional rollback when i will get checked exception from "invokeProcedureForLead" method(code mentioned below). I have tried multliple ways and some reference still
it is not working for me .
For more understanding please find below code
#Transactional(rollbackFor = Exception.class)
public LeadResponseDTO processDataInDB(LMCRAResponseData lmcraResponse,
Boolean crnPresentFlag, Map<Integer, Integer> craProcData,
Map<Integer, Integer> crnProcData,LeadResponseDTO leadResponseDTO,LMCRARequestData lmcraRequestData) throws CRAProcessDBException,SQLException, CRAProcessClientException {
try{
leadResponseDTO = extractDecision(lmcraResponse,crnPresentFlag);
decisionEngineResponseDao.invokeProceduresForLead(craProcData, crnProcData, lmcraResponse);
}catch(Exception e){
log.error("error in invokeProcCalls", e);
if (masterErrorCodes.getErrorDTO("6006") != null)
logException(lmcraResponse, masterErrorCodes.getErrorDTO("6006"));
leadResponseDTO=new LeadResponseDTO();
getLeadResponseDTO(lmcraRequestData,leadResponseDTO,e.getMessage());
}
return leadResponseDTO;
}
public void invokeProceduresForLead(Map<Integer, Integer> craProcData,
Map<Integer, Integer> crnProcData, LMCRAResponseData lmcraResponseData) throws Exception {
int noCRNFlag = 0;
String commonLogs = CommonUtil.printDECommonLogs(lmcraResponseData);
if (lmcraResponseData.isBureauMatch() && crnProcData.isEmpty())
noCRNFlag = 1;
if (lmcraResponseData.isBureauMatch()
&& invokeProcLeads(craProcData, DBConstants.CALL_PROC_PROCESS_CRA_DATA_LEAD,
Integer.parseInt(lmcraResponseData.getCaseID())) != null) {
log.info("invokeProcLeads for Cra block - 1 for runId {} " , commonLogs);
throw new CRAProcessDBException("error in invokeProcCalls for CRA");
}
if (crnProcData != null
&& !crnProcData.isEmpty()
&& invokeProcLeads(crnProcData, DBConstants.CALL_PROC_PROCESS_CRN_DATA_LEAD,
Integer.parseInt(lmcraResponseData.getCaseID())) != null) {
log.info("invokeProcLeads for crn block - 2 for runId {} " , commonLogs);
throw new CRAProcessDBException("error in invokeProcCalls for CRN");
}
if (((crnProcData == null || crnProcData.isEmpty()) || !lmcraResponseData.isBureauMatch())
&& invokeNoCrnForLeads(DBConstants.CALL_PROC_PROCESS_NO_CRN_DATA_LEAD,
Integer.parseInt(lmcraResponseData.getCaseID()), noCRNFlag) != null) {
log.info("invokeNoCrnForLeads block - 3 for runId {} " , commonLogs);
throw new CRAProcessDBException("error in invokeProcCalls for NOCRN");
}
I think the code needs to change like this -
log.error("error in invokeProcCalls", e);
if (masterErrorCodes.getErrorDTO("6006") != null)
logException(lmcraResponse, masterErrorCodes.getErrorDTO("6006"));
leadResponseDTO=new LeadResponseDTO(); getLeadResponseDTO(lmcraRequestData,leadResponseDTO,e.getMessage());
}
throw e;
Note that **throw e; ** line added..
The problem is you are throwing an exception from internal call, but then swallowing it in outer method. So the exception is never thrown from outer method, which results in no rollback happening.

My Custom Exception is not thrown, instead the ArrayOutOfBoundsException Is thrown (JunitTest Error)

i have a Problem with my Custom Exception, i want to throw a Custom Exception when the entered row/col does not excist in my shelf[][] which only kind of works. The custom exception does get thrown when i compile my main (error message is printed)- even though the throw part in my Code is apparently never reached (https://i.stack.imgur.com/1OY52.png) - but it also throws the ArrayIndexOutOfBoundsException. So when i Junit test my method for throwing InvalidRow/ColumnException it fails because it throws the ArrayOutOfBoundsException.
How do i solve this problem so my Junit test assertThrows(InvalidRowException.class,() -> shelf.addItem(3, 0, bottle)); doesnt catch the ArrayIndexOutOfBoundsException but instead only my InvalidRowException?
This is my Exception Class:
public class InvalidRowException extends ArrayIndexOutOfBoundsException {
public InvalidRowException(int wrongRow){
super("passed Row " + wrongRow + " doesnt excist.");
}
}
This is my Method
public void addItem(int row, int coll, Product product) throws InvalidRowException, InvalidColumnException {
if (row < 0 | row > shelf.length)
throw new InvalidRowException(row);
if (coll < 0 | coll > shelf[1].length)
throw new InvalidColumnException(coll);
try {
if (!(product instanceof Placeable)) {
throw new ProductNotPlaceableException(product);
} else if (shelf[row][coll] != null) {
System.out.println("Replacing product with serial " + shelf[row][coll].getSerialNumber()
+ " by product with serial " + product.getSerialNumber());
shelf[row][coll] = product;
} else {
shelf[row][coll] = product;
}
} catch (ProductNotPlaceableException e) {
System.out.println(e.getMessage());
}
}
You throw exception for
row > shelf.length
You should check for row > shelf.length -1 as arrays are 0 based
Similarly for coll the correct check is coll> shelf[row].length-1

java8 - Optional- How to use it correctly?

The cityStr is a String, and it would be a null or "". I want to turn it to a int and if it's greater than 0, then I will print "the city is exist".
if (StringUtils.isNotBlank(cityStr)) {
if (Integer.parseInt(cityStr) > 0) {
System.out.println("the city is exist");
}
}
I want to used the below code to replace the above code, but I got a exception. How can I use it correctly? Thanks so much for your answer.
if (Optional.ofNullable(cityStr)
.map(Integer::parseInt)
.filter(city -> city > 0)
.isPresent()) {
System.out.println("the city is exist");
}
And the below is the exception information:
Exception in thread "main" java.lang.NumberFormatException: For input string: ""
at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
at java.lang.Integer.parseInt(Integer.java:592)
at java.lang.Integer.parseInt(Integer.java:615)
at java.util.Optional.map(Optional.java:215)
You are trying to parse a number from an empty String. That throws the exception. It has nothing to do with Optional.
Maybe you thought that an empty string would be 'nullish' - like an empty String being falsy in javascript.
To get rid of the exception, assign null or a number to cityStr.
You could write it as :
String cityStr = null;
if (Optional.ofNullable(cityStr)
.map(Integer::parseInt)
.filter(city -> city > 0)
.isPresent()) {
System.out.println("the city is exist");
}
If you are expecting non numeric string you've to handle that yourself in the map method.
As suggested by #fastcodejava I made minor changes to the program, please take a look below:
public static void main(String[] args) throws NoSuchAlgorithmException {
String cityStr = "1";
Optional<String> cityOptional = Optional.ofNullable(cityStr)
.map(MainClass::parseInt)
.filter(integer -> integer > 0)
.map(integer -> "city exists");
String cityString = cityOptional.orElse("city does not exists");
System.out.println(cityString);
}
public static int parseInt(String str) {
try {
return Integer.parseInt(str);
} catch (NumberFormatException e) {
// Eating e for unknown reason
return -1;
}
}
Where MainClass is the class for main method MainClass.java

weird java behavior with nested closures losing captured variable values

OK this is going to be a bit long and complex, I'm hoping for some rubber ducking here.
I have this code, which is actually a bit more complex, but I think i did a reasonable job of simplifying it:
private Result getResult(Request request, RequestType type) {
final String date = request.getData(); // marker 1
final DataSource jdbcDataSource = getDataSource();
final JdbcOperations jdbcTemplate = newJdbcOperations(jdbcDataSource);
final TransactionTemplate transactionTemplate = createTransactionTemplate(jdbcDataSource);
Supplier<Integer> createResult = () -> transactionTemplate.execute(transactionStatus -> {
List<Map<String, Object>> rs = jdbcTemplate.queryForList("SELECT * FROM table");
if (rs.size() > 0) {
return ((Number) rs.get(0).get("count")).intValue();
} else {
log.info(request + " not found in table");
}
if (type == TYPE1) {
//...
} else {
throw new RuntimeException("unexpected type:" + type); // marker2
}
return 0;
});
int retryCount = 0;
while (retryCount < 5) {
try {
totalCount = createResult.get();
break;
} catch (DuplicateKeyException | DeadlockLoserDataAccessException e) {
// log
}
retryCount++;
}
}
This works fine, except that today the app server got into a state where it stopped working. The method enters, gets past line "marker1" so we know request is not null, then proceeds to log "null not found in table" suggesting that request turned into null and then throws runtimeException "marker2" because type has turned into null as well.
I hate to say it but this really just smells like a bug in JVM, but this really should be the last to consider, so I'm hoping that you, my dear rubber duck, would have some ideas.

This codes can't check NoResultException

This is the Code I was made. It shouldn't get and enter to NoResultException, but it doesn't as expected. There is an unused data. I try to print out, here is the output : "[ ]"
private void deleteButtonActionPerformed(java.awt.event.ActionEvent evt) {
try {
int row = tableDataRangka.getSelectedRow();
String idRangka = tableDataRangka.getValueAt(row, 0).toString();
System.out.println( relasiRumahkayuRangkaDAO.getRelasiByIdRangka(idRangka).toString() );
} catch (NoResultException nre) {
// Doing something..
} catch (Exception ex) {
Logger.getLogger(MasterDataProjectUI.class.getName()).log(Level.SEVERE, null, ex);
}
}
Here is the code of method "getRelasiByIdRangka" :
public List<RelasiRumahKayuRangka> getRelasiByIdRangka(String idRangka) throws Exception{
initEntityManager();
List<RelasiRumahKayuRangka> rrDrs = new ArrayList<>();
Query q = em.createNamedQuery("RelasiRumahKayuRangka.findByIdRangka");
q.setParameter("idRangka", idRangka);
rrDrs.addAll(q.getResultList());
closeEntityManager();
return rrDrs;
}
And this one is the JPA query, findByIdRangka :
#NamedQuery(name = "RelasiRumahKayuRangka.findByIdRangka", query = "SELECT r FROM RelasiRumahKayuRangka r WHERE r.relasiRumahKayuRangkaPK.idRangka = :idRangka"),
Do you guys know the solution, so the code can be catched by NoResultException ?
In your code. if the result set is empty then list will also be empty.
Make use of that situation and throw a desired exception.
In your getRelasiByIdRangka(String idRangka) add following changes.
public List<RelasiRumahKayuRangka>
getRelasiByIdRangka( String idRangka ) throws Exception {
initEntityManager();
// rest of the code here
// ...
// check if some results are found or not
if( rrDrs.isEmpty() ) { // or ( rrDrs.size() == 0 )
throw new NoResultException( "No results found" );
} // if empty
// this should be a filled in list
return rrDrs;
} // end of method

Categories

Resources