Como executar os testes no argumento de que um controlador passa para o modo de exibição no Play Framework

StackOverflow https://stackoverflow.com//questions/20005032

  •  20-12-2019
  •  | 
  •  

Pergunta

Na nossa maneira de jogar aplicação de cada controlador de função obtém dados a partir do banco de dados (ou de alguma outra forma) e passa esses valores para o resultado

def index = Action { implicit request =>
    val newsItems: List[String] = fetchNewsFromDB()
    Ok(views.html.home.index(newsItems))
  }

def fetchNewsFromDB() = List("Headline1", "Headline2")

Eu estou escrevendo testes usando specifiactions (com base na documentação http://www.playframework.com/documentation/2.2.x/ScalaTest)

De acordo com esta documentação pelo controlador da seguinte forma.No próximo teste, eu quero certificar-se de que a página de índice contém um cabeçalho.Eu faço isso verificando se existe uma div com a classe "manchete"

"Example Page#index" should {
    "should contain a headline" in {
      val controller = new TestController()
      val result: Future[SimpleResult] = controller.index().apply(FakeRequest())
      val bodyText: String = contentAsString(result)
      bodyText.toLowerCase must contain("<div class=\"headline\"")
    }
  }

No entanto, eu gostaria de, ao invés de verificar se a lista newsItems que o controlador passa para o modo de exibição não é vazio.

Qual é a melhor maneira de fazer isso?É possível fazer isso de uma forma genérica para que pouco a modificação dos controladores é necessário?

Foi útil?

Solução

Eu também fiquei frustrado que eu não conseguia interceptar os parâmetros em seu caminho para o modelo - e, na verdade, pode tornar-se extremamente difícil até mesmo para obter o modelo para compor em todos os nos testes, se você tem um monte de "estado" em suas páginas (por exemplo, implicits que fornecer o objeto de usuário, navegação ajudantes, etc.).

O que eu acabei fazendo foi a colocação de uma "costura" para testabilidade na minha controladores;em meus testes, eu ampliar o controlador em teste, substituição de renderização HTML função com um escarnecido, que eu possa usar para verificar os parâmetros.

Aqui está um exemplo simples baseado em suas "notícias" Ação;primeiro, o controlador, que não é mais um object assim, podemos estendê-lo:

object Application extends ApplicationController

trait ApplicationController extends Controller {

  def newsAction = Action {
    Ok(renderNews("this is the news"))
  }

  def renderNews(s:List[String]):Html = html.sandbox(s)
}

O renderNews método nos dá o "teste da costura".Eu acho que ele realmente melhora a legibilidade do controlador de métodos muito, o que é bom :-)

Agora, o teste de unidade:

class ApplicationSpec extends Specification with Mockito {

  val mockedNewsRenderer = mock[List[String] => Html]

  val controller = new ApplicationController {
    override def renderNews(s:List[String]) = mockedNewsRenderer(s)
  }

  "Application News Controller" should {

    "Pass a non-empty list of news items to the template" in {
      val result = controller.newsAction(FakeRequest())

      status(result) must beEqualTo(200)

      val captor = ArgumentCaptor.forClass(classOf[List[String]])

      there was one(mockedNewsRenderer).apply(captor.capture())
      val theArgument = captor.getValue
      theArgument.isEmpty must beFalse
    }
  }
}

Criamos um mock para stand-in para o renderNews função de estender o controlador de modo que podemos substituir em (note que nós não altere mais nada sobre ele, claro) e, em seguida, chamar a ação como normal.Observe que temos ainda um padrão de Jogo Result assim, podemos ainda verificar códigos de status etc, mas a gente pode usar o Mockito verificar a funcionalidade que é construído para Specs2, juntamente com Mockito do ArgumentCaptor instalação para afirmar que o nosso modelo foi, de fato, chamados, e que foi fornecido com um não-vazia lista de cadeias de caracteres.

Esta abordagem tem funcionado bem para mim - ele torna possível para ficar realmente bom de cobertura de código do seu controladores de rápida execução e de fácil escrever testes de unidade.

Outras dicas

Você tem uma pergunta muito boa e um ponto muito válido, em testes de controladores, mas estou com medo de que ele não pode ser feito facilmente.O problema é que os pontos de vista de compilação para Scala funções significado quando você chamar views.html.home.index(newsItems) ele vai retornar um objeto de Html, que já tem o Html juntos e compilado.Se você gostaria de testar o que se passou em que você precisa para interceptá-lo antes que a exibição é chamado.

Para resolver isso, você teria que reescrever seus controladores, movendo toda a sua lógica de negócios do controlador e tem somente o necessário solicitar o código de manipulação de lá.Que seria quase mais fácil de testar.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top