ユニットテスト用のメールサーバsubethasmtpがあることを知りました

JUnitで使えるメールサーバ[SubEtha SMTP](https://github.com/voodoodyne/subethasmtp)があることを知りました。ユニットテスト用の仮想マシンを立てていた手間が省けて助かります。

以下のような感じです。

```java:MailSender.java（テスト対象）
import java.util.Date;
import java.util.Properties;

import javax.mail.Address;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;

import lombok.Data;

@Data
public class MailSender {
	private String from;
	private String host;
	private Integer port;

	public MailSender(final String host, final int port) {
		this.host = host;
		this.port = port;
	}

	public void send(String from, String to, String subject, String text)
			throws AddressException, MessagingException {
		Properties prop = new Properties();
		prop.put("mail.smtp.host", getHost());
		prop.put("mail.smtp.port", getPort().toString());
		Session session = Session.getDefaultInstance(prop);
		MimeMessage mime = new MimeMessage(session);
		mime.addFrom(InternetAddress.parse(from));
		Address[] tos = { new InternetAddress(to) };
		mime.setRecipients(Message.RecipientType.TO, tos);
		mime.setSubject(subject, "iso-2022-jp");
		mime.setText(text);
		mime.setSentDate(new Date());
		Transport.send(mime);
	}
}

```

```java:MailServerTest（ユニットテスト）
import org.junit.*;

import static org.hamcrest.MatcherAssert.*;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.fail;

import java.util.List;

import javax.mail.MessagingException;

import lombok.val;

import org.subethamail.wiser.Wiser;
import org.subethamail.wiser.WiserMessage;

public class MailSenderTest {
	
	private static Wiser wiser;
	
	final static String hostName = "localhost";
	final static int port = 2500;
	
	@BeforeClass
	public static void setUpBeforeClass() throws Exception {
		// メールサーバを立てる
		wiser = new Wiser();
        wiser.setPort(port);
        wiser.setHostname(hostName);
        wiser.start();
	}

	@AfterClass
	public static void tearDownAfterClass() throws Exception {
    	// メールサーバを落とす
    	wiser.stop();
	}

	@Test
	public void test() {
		final String expectTo = "to@devel.local";
		final String expectFrom = "from@devel.local";
		final String expectSubject = "Hello World";
		final String content = "What a nice weather today\nDo not you think so?";

		val mailer = new MailSender(hostName, port);
		try {
			mailer.send(expectFrom, expectTo, expectSubject, content);
			
			// メール内容を検査
	        List<WiserMessage> messages = wiser.getMessages();
	        for (WiserMessage wiserMessage : messages) {
	        	assertThat(wiserMessage.getEnvelopeSender(), is(expectFrom));
	        	assertThat(wiserMessage.getEnvelopeReceiver(), is(expectTo));
	        	try {
					assertThat(wiserMessage.getMimeMessage().getSubject(), is(expectSubject));
				} catch (MessagingException e) {
					fail("題名を取得できない");
				}
	        }

		} catch (MessagingException e) {
			fail("期待していない例外が発生");
		}
	}

}

```

```groovy:build.gradle
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'maven'
apply plugin: 'provided-base'

buildscript {
    repositories {  
        maven { url 'http://jcenter.bintray.com' }
    }
    dependencies {
        classpath 'com.netflix.nebula:gradle-extra-configurations-plugin:1.12.+'
    }
}
 
sourceCompatibility = "$project.java_version"
targetCompatibility = "$project.java_version"
 
version = "$project.spec_version"
group = "$project.app_group"
 
repositories {
    maven { url "http://repo.maven.apache.org/maven2" }    
}
 
dependencies {
	compile 'javax.mail:mail:1.+'
    provided 'org.projectlombok:lombok:1.14.+'
    
    testCompile 'junit:junit:4.11', {
        transitive = false
    }
    testCompile 'org.hamcrest:hamcrest-all:1.3'
    testCompile("org.subethamail:subethasmtp:3.1.+") // 組込みサーバ
}
 
def defaultEncoding = 'UTF-8'
tasks.withType(JavaCompile) {
    options.encoding = defaultEncoding
}
 
jar {
    manifest {
        attributes 'Implementation-Title': "$project.app_description",
                   'Implementation-Version': version + "-$project.patch_version"
    }
}
 
clean {
    delete 'bin', 'target', 'logs'
}

```

```properties:gradle.properties
spec_version = 0.9.0
patch_version = p0
 
app_group = org.example
app_name = example
app_description = "This is a example"
 
java_version = 1.8
```