在测试过程中,如何伪造 MailerPlugin.send 才能收到已发送的电子邮件?

During testing, how can I fake MailerPlugin.send so I can get the sent email?

在测试期间,我希望在 Play 2.3 中伪造 play.api.libs.mailer.MailerPlugin,以便我可以掌握正在发送的电子邮件。我该怎么做?

应用代码

package services
import play.api.libs.mailer._
import play.api.Play.current

object EmailService {
  def sendUserNotification(to: String, subject: String, content: String): Unit = {
    val email = Email(
      "subject",
      "Admin <admin@test.com>",
      Seq(to),
      bodyHtml = Some(s"""<html>
      | <body>
      |   $content
      | </body>
      | </html>
      | """.stripMargin)
    )
    // Should like to fake this from tests, but how?
    MailerPlugin.send(email)
  }
}

测试代码

object Test {
  def testEmail(): Unit = {
    // How do I get hold of the sent email?
    EmailService.sendUserNotification("user@user.com", "Test", "Testing...")
  }
}

你有很多选择:

最简单也可能是最好的方法:将函数与副作用分离,将创建逻辑分离到一个单独的方法中并为此编写测试,然后您可以从副作用中调用它 sendUserNotification

def createUserNotification(...): Email = ...

def sendUserNotification(...): Unit = 
  MailerPlugin.send(createUserNotification(...))

如果您已经编写了很多已经使用您的服务的控制器等,并且您想要编写测试来检查这些发送电子邮件是否有一组插件 class 要禁用的名称和一组插件 class 要在 FakeApplication 上从播放测试实用程序启用的名称,因此您可以在测试中提供 EmailPlugin 的虚假实现,它只收集已发送的电子邮件。 play.api.test.WithApplication 接受一个 FakeApplication 到它的构造函数,它将在 运行 测试时使用。

您可以依赖注入实际的邮件操作,方法是使电子邮件插件成为您在使用它的地方注入的东西,作为构造函数参数或作为抽象方法或值,甚至是传递给发送的函数方法。例如:

sendUserNotification(...)(send: Email => Unit)

trait EmailService {
  def actuallySend(email: Email): Unit
}

object Emails extends EmailService {
  def actuallySend(email: Email) = MailerPlugin.send(email)
}