Monday 19 March 2012

Maven Shortcuts

Maven is cool, but repeatably typing the long maven commands is little bit boring and waste of time. one simple solution is to create set of batch files for the repeatably used commands.

Most of us use our own set of batch files, I thought of organizing them in single place (atleast for me whenever I move to new project I don't need to create my own batch files again and again). I have created a project in github for this purpose and have included very minimum number of very frequently used commands.

The project located at https://github.com/nutpan/Maven-Shortcuts

you can download that and place it your classpath to save your time with maven commands.

Purposefully I have kept the number of commands as minimum, please send me your frequently used commands by raising a issue at https://github.com/nutpan/Maven-Shortcuts/issues or by adding a comment here, I would like to grow the collection in this way on need basis, so that it will have only the most wanted comments.

Below are the shortcuts and their actual maven command


mvnc - mvn clean
mvni - mvn install

mvnci - mvn clean install
mvnciwt - mvn clean install with out tests
mvnt - mvn test
mvnt %1 - mvn test on single test file (eg : mvnt MyTest)
mvnee - mvn eclipse:eclipse


For Windows, copy all the batch files in to a folder and add the folder in classpath
For linux/unix, you can copy the sh files into bin folder and give executable permission using commands in makeItExec.sh

Sunday 18 March 2012

Liquibase Maven Plugin - Issue with non local database

There is an option in Liquibase to prompt for permission if the database it connects to is not in local system.
By default this option is turned off as per the Liquibase documentation, but when execute through maven Liquibase plugin seems like this default is other way round and by default it is true and even if add the property

promptOnNonLocalDatabase=false


to liquibase properties file, it is not changing its behavior, when we execute this in non head environments like unix, it does through following exception


No X11 DISPLAY variable WAS set, this program aims Performed year operation Which
Requires it.
at java.awt.GraphicsEnvironment.checkHeadless (GraphicsEnvironment.java: 159)
at java.awt.Window.(Window.java: 407)
at java.awt.Frame.(Frame.java: 402)
at java.awt.Frame.(Frame.java: 367)
at $ javax.swing.SwingUtilities SharedOwnerFrame.(SwingUtilities.java: 1731)
at javax.swing.SwingUtilities.getSharedOwnerFrame (SwingUtilities.java: 1808)
at javax.swing.JOptionPane.getRootFrame (JOptionPane.java: 1673)
at javax.swing.JOptionPane.showOptionDialog (JOptionPane.java: 846)
at javax.swing.JOptionPane.showConfirmDialog (JOptionPane.java: 779)
at javax.swing.JOptionPane.showConfirmDialog (JOptionPane.java: 741)
at liquibase.SwingUIFacade.promptForNonLocalDatabase (SwingUIFacade.java: 15)



Solution to this problem is ,


Just add the following in to the maven plugin configuration section

  <promptOnNonLocalDatabase>false</promptOnNonLocalDatabase>

Example :


<build>
      <plugins>
        <plugin>
          <groupId>org.liquibase</groupId>
          <artifactId>liquibase-maven-plugin</artifactId>
          <version>2.0.1</version>
          <executions>
            <execution>
              <phase>process-resources</phase>
              <configuration>
                <propertyFile>target/classes/liquibase.properties</propertyFile>
                <promptOnNonLocalDatabase>false</promptOnNonLocalDatabase>
              </configuration>
              <goals>
                <goal>update</goal>
              </goals>
            </execution>
          </executions>
        </plugin>
      </plugins>
    </build>

Hope this helps....

Thursday 1 March 2012

Mock Testing for Java Mail

Testing the email related code comes with its own challenges,
  • we may need a dedicated test mail server with test mail box
  • verification part of the test can not be executed right after the setup of test due to the latency in the mail delivery (due to milliseconds delay the test may fail).
  • setup and maintenance may cost its own penalties
Especially in CI and Unit testing, testing email part of the code is not so easy.

There are few good alternatives with Mock Mail testing, one of the interesting and very handy options is Mock-JavaMail. It does not require any additional setup or configuration, just drop the jar into classpath, that's all it requires. 

It redirects all the mails to in-memory mail box which can be easily used in unit tests.

Lets see this with small example. 

Maven Dependency configuration 

Include the following dependency in maven (if not using maven, just drop the jar to classpath)

               <dependency>
        <groupId>org.jvnet.mock-javamail</groupId>
  <artifactId>mock-javamail</artifactId>
  <version>1.9</version>
  <scope>test</scope>
  </dependency>

Example Mail Code

I have used Apache Commons Mail api for this example for simplicity, but works fine with any implementation of Java Mail.

package com.nutpan.example;

import org.apache.commons.mail.Email;
import org.apache.commons.mail.EmailException;
import org.apache.commons.mail.SimpleEmail;

public class MyMailSender {

public void sendMail(String to, String from, String subject, String msg) throws EmailException {
Email email = new SimpleEmail();
email.addTo(to);
email.setFrom(from);
email.setSubject(subject);
email.setMsg(msg);
email.setHostName("testmail.com");
email.send();
}

}

JUnit Test Code

package com.nutpan.example;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertTrue;

import java.io.IOException;
import java.util.List;
import java.util.Properties;

import javax.mail.Folder;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.Store;

import org.apache.commons.mail.EmailException;
import org.junit.Before;
import org.junit.Test;
import org.jvnet.mock_javamail.Mailbox;


public class MyMailSenderTest {

private MyMailSender mailSender;

@Before
public void setUp() {
mailSender = new MyMailSender();
//clear Mock JavaMail box
Mailbox.clearAll();
}

@Test
public void testSendInRegualarJavaMail() throws MessagingException, IOException, EmailException {

String subject = "Test1";
String body = "Test Message1";
mailSender.sendMail("test.dest@nutpan.com", "test.src@nutpan.com", subject, body);
Session session = Session.getDefaultInstance(new Properties());
Store store = session.getStore("pop3");
store.connect("nutpan.com", "test.dest", "password");

Folder folder = store.getFolder("inbox");

folder.open(Folder.READ_ONLY);
Message[] msg = folder.getMessages();

assertTrue(msg.length == 1);
assertEquals(subject, msg[0].getSubject());
assertEquals(body, msg[0].getContent());
folder.close(true);
store.close();
}

@Test
public void testSendInMockWay() throws MessagingException, IOException, EmailException {

String subject = "Test2";
String body = "Test Message2";
mailSender.sendMail("test.dest@nutpan.com", "test.src@nutpan.com", subject, body);
List<Message> inbox = Mailbox.get("test.dest@nutpan.com");
assertTrue(inbox.size() == 1);
assertEquals(subject, inbox.get(0).getSubject());
assertEquals(body, inbox.get(0).getContent());

}
}


First Test uses the regular Javamail approach for reading the mail and the other one uses the Mock-JavaMail  approach to read the mails from the Mock Email Server. I have included the whole import statements to show the different apis from where the classes imported (JavaMail and some from Mock-JavaMail).

You can get more information about this work at 

http://java.net/projects/mock-javamail

There are few more alternatives too, following are some of the few

Wiser
dumbster
Aspirin


give a try and keep me posted.... Better tests better software...