Debugging Fitnesse (SLIM)

FitNesse is one of wiki based frameworks available in the open source world which can be used for projects which require

  • Acceptance Testing
  • Integration Testing
  • BDD ( Behavior Driven Development) etc

One of the most obvious reasons why FitNesse is so popular is readability factor. Tests written in FitNesse are readable by humans and can be used as a front end for non technical people to sign off the requirements. One of the powerful features of FitNesse is the way it converts the Tables on wiki to JAVA calls. However, there are times when we need to debug these FitNesse tests to see whats going on.

This blog will cover how one can set up FitNesse pages for debug mode.

Most of the IDEs today provide an option for remote debugging via a port. We can leverage on the same to assist our debugging.

Step 1) Start the FitNesse server

Step 2) Navigate to the page which needs to be debug. For example http://<machine address where FitNesse server has been started>:<port where FitNesse server is listening>/<Name of the Test Case>.

Step 3) Define the following variable on the test page.

!define REMOTE_DEBUG_COMMAND {java -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=8000 -cp %p %m}

In the above statement make sure to change the port 8000 according to port availability on your machine.

Step 4) Start the test bu using the following parameters

responder=test&remote_debug=true

For example if the Test we wanted to debug was reachable via http://localhost:8080/Test1 then just change the URL to http://localhost:8080/Test1?responder=test&remote_debug=true.

Step 5) Open your favourite IDE. Create a remote debug on port 8000 (as defined Step 3).

Step 6) And we are all set to do some debugging.

GreenMail !!!Test your mail functionality

There are times when we want to test the mail functionality, when we run integration tests. Many a times we don’t have separate SMTP relay server for each environment. And during tests we would not want to use the SMTP server pointing to production.

The following are the options we can use

  1. Ask for a test SMTP server. (Not always easy to get).
  2. Use GreenMail java API.

As a part of this blog I am going to explain the following about GreenMail Java API.

  1. GreenMail protocol support.
  2. Starting and Stopping GreenMail server.
  3. Configuring GreenMail server during start up.
  4. Testing GreenMail set up.
  5. Adding users and Folder listeners.

GreenMail protocol support

GreenMail supports the following protocols out of the box

  1. SMTP
  2. SMTPS
  3. POP3
  4. POP3S
  5. IMAP
  6. IMAPS

 Starting and Stopping GreenMail Server

Starting and stopping GreenMail server is as easy as highlighted below.


import com.icegreen.greenmail.util.GreenMail;

 

private GreenMail greenMail;

public  void startServer()

{

greenMail = new GreenMail();

greenMail.start();

}

 

public void stopServer()

{

greenMail.stop();

}

By using the code above GreenMail server will start mail servers for all the protocols . i.e. SMTP, SMTPS,POP3,POP3S,IMAP and IMAPS.

However, we may not want all the servers running at the same time. This can be achieved by configuring GreenMail server at startup.

The next section highlights how this can be done.

 Configuring GreenMail server during start up

We can configure GreenMail server to only start SMTP server or a combination of SMTP and SMTPS servers etc.

This is achieved by passing ServerSetup object to GreenMail constructor.

ServerSetup object constructor takes three arguments

  • port (port at which the server has to listen to).
  • bindAddress (ip address  or machine name where you want the server to bind to).
  • protocol (possible values will be ServerSetup.PROTOCOL_SMTP,ServerSetup.PROTOCOL_SMTPS etc).

ServerSetup object itself has default setup configuration for each of the supported protocols which can be used directly if you dont want to override any setting.


ServerSetup[] serverSetUps = new ServerSetup[]{ServerSetup.SMTP,ServerSetup.SMTPS};

GreenMail greenMail = new GreenMail(serverSetUps);

greenMail.start();

The above code will only start SMTP and SMTPS servers.

Now that all the configuration is done and the servers are running using the configuration defined. The next step is to test the setup.

 

Testing GreenMail set up

The easiest way to test GreenMail set up is by using the following code

public void testYourSendingCode() throws Exception {
GreenMail greenMail = new GreenMail(); //uses test ports by default
greenMail.start();
GreenMailUtil.sendTextEmailTest("to@localhost.com", "from@localhost.com", "subject", "body");
assertEquals("subject", greenMail.getReceivedMessages()[0].getSubject());
greenMail.stop();
//Thats all
}

Adding users and Folder listeners

Till now we looked at how to configure ,setup and test GreenMail server. However, we can not just use greenMail.getReceivedMessages() to track all incoming mails. What if application sends different mails to different users depending on configuration.

In order to achieve this , GreenMail offers a functionality to addUsers.


GreenMailUser greenMailUser = greenMail.setUser("email_address","password");

For every user added we access different folders created for that user. And one of the important one being “INBOX” folder.

Having access to “INBOX” folder gives us an advantage to attach a FolderListener (interface in  the package com.icegreen.greenmail.store) to the folder.  FolderListener can be useful in testing certain mails coming to certain mail boxes only.  FolderListener will be notified automatically whenever

  • Mail arrives in that folder [exposed via added method in FolderListener].
  • If the Folder flags are updated [exposed via flagsUpdated(int msn, Flags flags, Long uid) method].
  • When a message is expunged [exposed via expunged(int msn) method].
  • And when a mailbox is deleted [ exposed via mailboxDeleted() method].

The complete code along with usage of FolderListener is as follows


package com.sandp.mail;

import com.icegreen.greenmail.store.FolderException;
import com.icegreen.greenmail.store.FolderListener;
import com.icegreen.greenmail.store.MailFolder;
import com.icegreen.greenmail.store.SimpleStoredMessage;
import com.icegreen.greenmail.user.GreenMailUser;
import com.icegreen.greenmail.util.GreenMail;
import com.icegreen.greenmail.util.ServerSetup;

import javax.mail.Flags;
import javax.mail.MessagingException;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

 

public class MailUtil {
private GreenMail greenMail = new GreenMail();
private Map<String,MailDTO> userMap = new HashMap<String, MailDTO>();
private Map<String,Integer> currentMailIndexNumber = new HashMap<String, Integer>();

private static MailUtil _instance;

private MailUtil()
{
greenMail = new GreenMail(ServerSetup.ALL);
}

public static synchronized MailUtil getInstance()
{
if(_instance == null)
{
_instance = new MailUtil();
}
return _instance;
}

public void startServer()
{
greenMail.start();
}

public void stopServer()
{
greenMail.stop();
}

public boolean addUserWithEmailAndPassword(String email,String password)
{
GreenMailUser greenMailUser = greenMail.setUser(email, password);
MailDTO mailDTO = new MailDTO();
mailDTO.setUser(greenMailUser);
MyFolderListener userInboxFolderListener = new MyFolderListener(email);
mailDTO.setUserInboxFolderListener(userInboxFolderListener);
try {
MailFolder inbox = greenMail.getManagers().getImapHostManager().getInbox(greenMailUser);
inbox.addListener(userInboxFolderListener);
} catch (FolderException e) {
e.printStackTrace();
}
userMap.put(email,mailDTO);
return true;
}

public synchronized boolean  waitForEmailToArriveForUserForSecondsForAMaximumOfTimes(String email, int seconds, int retryAttempt)
{
MyFolderListener listener = userMap.get(email).getUserInboxFolderListener();
try {
while(!listener.mailArrived() && retryAttempt > 0)
{
wait(seconds*1000);
retryAttempt --;
}
} catch (InterruptedException e) {
e.printStackTrace();
}
return listener.mailArrived();
}

public Object getCurrentMessageForUser(String email)
{
try {
MailFolder inbox = greenMail.getManagers().getImapHostManager().getInbox(userMap.get(email).getUser());
return ((SimpleStoredMessage) inbox.getMessages().get(currentMailIndexNumber.get(email) -1)).getMimeMessage().getContent();

} catch (FolderException e) {
e.printStackTrace();
} catch (MessagingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}

public class MyFolderListener implements FolderListener {
private boolean mailArrived = false;
private String email;

public MyFolderListener(String email) {
this.email = email;
}

@Override
public void expunged(int msn) {

}

@Override
public void added(int msn) {
mailArrived = true;
currentMailIndexNumber.put(email,msn);
}

@Override
public void flagsUpdated(int msn, Flags flags, Long uid) {

}

@Override
public void mailboxDeleted() {

}

boolean mailArrived()
{
return mailArrived;
}
}

public GreenMail instance()
{
return greenMail;
}
}

And code for MailDTO is


package com.sandp.mail;

import com.icegreen.greenmail.user.GreenMailUser;

public class MailDTO {
private GreenMailUser user;
private MailUtil.MyFolderListener userInboxFolderListener;

public GreenMailUser getUser() {
return user;
}

public void setUser(GreenMailUser user) {
this.user = user;
}

public MailUtil.MyFolderListener getUserInboxFolderListener() {
return userInboxFolderListener;
}

public void setUserInboxFolderListener(MailUtil.MyFolderListener userInboxFolderListener) {
this.userInboxFolderListener = userInboxFolderListener;
}
}

 

This concludes how GreenMail can be used for testing puropses.

Running multiple JBOSS server for debugging.

Many a times production boxes are load balanced and there will be more than one instance of application server running. During development  phase we test the applications on single node, and it becomes very critical to test the application on multiple nodes, especially when there is some in-memory datagrid or HA-JNDI etc.

It is at these times when we search for any existing environments where in we can test our application. Not always its very easy to get our hands on these environments as they are always used by other tasks with more priorities. In these situation the following tip will come in very handy.

Follow these steps to run multiple instances of JBoss on the same machine.

1) Copy all default directory under <JBOSS_HOME>/server/ in to another directory say by name “instance2?.

2) Effectively this means there would be another directory under <JBOSS_HOME>/server/ by name “instance2?.

3) Now in order to start “instance2? open command prompt navigate to <JBOSS_HOME>/bin and use the following command run.bat -c instance2 -Djboss.service.binding.set=ports-02.

4) This should start second instance on port 8280.

5) The default instance can be started using the normal command run.bat.