Category Archives: Java

Unit test – call the agel out of the stone

Angel

Angel, please come out of the stone

“I saw the angel in the marble and carved until I set him free” – Michelangelo

After the previous post when I managed to make Spring context wired for Unit test to run, now there’s more thing into it. Well, I gave my Test class the ability to do IOC (Inversion of Control), and from now they can call service beans, access databases, and so on… It seems the remaining should be easy, since the hardest part has been completed.

Well, things don’t easily go as we expect, in lots of occasions.

I actually made a running code, but when I try writing my first unit tests for my current working web-application, things turn bad. It turns out that I can’t write much meaningful non-trivial test, without making test-running-time tremendous slow. Why? It’s because:

1. Most of my code logic lies in the service. AND the service (in this project) OFTEN (if not always) works with Database. And when I says Database, it means the test is not the unit test anymore. It’s an Integration Test.

2. There’s some logic in my project which doesn’t relate to database. But I feels pretty confident about them – they are mostly simple. According to Pareto’s 80/20 rule, I don’t want to write tests that doesn’t enhance maintenance ability.

Those may be (some of) the reasons that my seniors don’t encourage me to write unit test. Unit tests are meant to be fast. If it’s not fast, there’s no reason to run it frequently, to help refactoring or development.

Another problem I meet is to set up the Database to a known state before running the test. Only then the test results will have some meanings.

So… are the efforts all useless. Absolutely no. The main problem here is that I need to stop regression bugs, by regularly running some kind of test. Whatever it is, but let me find bugs soon, and stop the system broken by ill-refactoring.

“And I have found the solution. The way to call the angel out of the stone”. If I can put up an in-memory database instead of Postgres, the running-time will be fast. I can also prepare the environment by database script or bootstrap code.

DBUnit seems to be a fair choice for a solution.

Quick note on Java time

The analog timer, From openclipart.org
One of the things I dislike most in Java is… unfriendly. DateTime manipulation is a typical example. I think at least one time, a Java developer will encounter this message: getYear() is deprecated.

Such a simple and often-heavily-used function is deprecated. So programmers must walk around by the Calendar class.

Calendar localCalendar = Calendar.getInstance();
Calendar utcCalendar = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
Date date = new Date();
localCalendar.setTime(date);
utcCalendar.setTime(date);

TimeZone localTimeZone = localCalendar.getTimeZone();

System.out.println("Year: " + localCalendar.get(Calendar.YEAR));
System.out.println("Month: " + localCalendar.get(Calendar.MONTH) + 1);
System.out.println("Day: " + localCalendar.get(Calendar.DATE));
System.out.println("Day of week: " + localCalendar.get(Calendar.DAY_OF_WEEK));
System.out.println("Hour: " + localCalendar.get(Calendar.HOUR_OF_DAY));
System.out.println("Minute: " + localCalendar.get(Calendar.MINUTE));

System.out.println("Timezone: " + localTimeZone.getDisplayName());
System.out.println("UTC Hour: " + utcCalendar.get(Calendar.HOUR));
System.out.println("UTC Minute: " + utcCalendar.get(Calendar.MINUTE));

Although Java big heads all have valid reasons for this inconvenience – which is the complexity of time manipulation, I still think this way is over-killing. Yes, no computer is accurate enough to calculate the correct solar time. But we are no astronomy expert, who cares if the time lacks one or two leap seconds*? Daylight saving stuffs is still necessary, but shouldn’t be too much of a problem.

In the end, I think Java powerful libraries should also make it easy to do simple tasks, instead thinking ahead too much for easy enlargement later**. With the Internet as popular as today, I think we can safely calculate “simple” time only, leaving the task to do additional astronomy calculation for the big servers, and cover the gaps by synchronizing.


(*) Like leap year, a leap second is sometimes added to our current timeline to cover the gaps between solar year & normal year. Because a leap second is too small,  people seldom notice. Reference: http://tycho.usno.navy.mil/leapsec.html

(**) Java has the reputation for easy scaling, and this is very true in my experience. On the opposite, small application is suddenly heavy at their very first cradle time, because a fair amount of efforts are put in “making room” for future changes.

Lesson learned from the Exception Filter

Long time ago, while I’m still a student, I have a chance to read Foundation of Programming“. “All exception should be captured, to show a understandable, friendly error message to customer”.

But now I realize that it’s not enough. In a recent web project, I created an exception filter to handle all exceptions popping out:

@Override
public void doFilter(ServletRequest request, ServletResponse response,
			FilterChain chain) throws IOException, ServletException {
		String errorMessage = "";

		try {
			chain.doFilter(request, response);
		} catch (SessionExpiredException e){
		    log.info(e.getMessage(), e);
                    errorMessage = "Your session has been expired";
                    request.sendRedirect(...);
		} catch (InvalidFacebookIdException e) {
                   // ...
		} catch(FacebookAccountAlreadyRegisteredException e) {
                   // ...
		} catch (Exception e) {
                   // ...
		}
	}

Do you notice the duplicate code? At any exception caught, the system must log the error, compose the mesage, then redirect to the error page.There are more than dozen of exceptions like that. How can we “clean” the code?

Thanks bro Tinh, here’s a (customized) solution:

@Override
public void doFilter(ServletRequest request, ServletResponse response,
			FilterChain chain) throws IOException, ServletException {
//...
		try {
			chain.doFilter(request, response);
		} catch (Exception e) {
                   errorMessage = e.getMessage();
                   log.error("Error occur: " + e.getMessage(), e);
                   res.sendRedirect(...);
		}
	}

All errors now are caught in one place: general Exception instead of concrete type.Two problems remain:

  • How to catch the right exception, because they are wrapped by Servlet Exception.
  • Guarantee all Customized Exception have a message

The answer for the first question:

private String getUsefulMessage(Exception e) {
Exception default = e.getMessage();
do {
if (e.getClass().getName().equals(InvalidFacebookId.class.getName())) return e.getMessage();
// ... same for other exceptions
e = e.getCause();
} while(e.getCause() != null);

return default;
} 

It’s the same, yes, for logic. But the later is more clearer.

The second question is more about coding policy than a technical problem, so I leave it out. In the case of our team, we decide that each exception should have an understandable getMessage().