2016-02-05 5 views
0

Я пишу тесты для вывода Json некоторых вызовов API в моем API, написанных с помощью Play на Scala. В моих тестах этот шаблон продолжает появляться, и я хотел бы дедуплицировать его.Сложный пользовательский Matcher

val response = sut.index()(FakeRequest()) 
val expected = Json.parse("""{ "channels":[] }""") 

status(response) must equalTo(OK) 
contentType(response) must beSome.which(_ == "application/json") 
contentAsJson(response) mustEqual expected 

Мой первый подход был такой:

def assertSameJson(response: Future[Result], expected: JsValue): Unit = { 
    status(response) must equalTo(OK) 
    contentType(response) must beSome.which(_ == "application/json") 
    contentAsJson(response) mustEqual expected 
} 

Но это не чувствует идиоматических вообще. Является ли кажется, что я добавляю XUnit утверждает в своих спецификациях

Я хотел бы кое-что приводит к

response must beSameJson(expected) 

Ближайший вещь, которую я сумел был

def beSameJson(other:Any) = 
    be_==(other) ^^ ((t: Future[Result]) => contentAsJson(t)) and 
    be_==(OK) ^^ ((t: Future[Result]) => status(t)) 

Но это не проверить на контент- типа, и я чувствую, что это просто очень трудно читать. Есть ли лучший способ написать этот Matcher?

ответ

1

Я не думаю, что есть лучший способ сделать это. Оператор ^^ точно предназначен для этой цели, чтобы преобразовать информацию перед применением другого соединителя. and может использоваться для объединения более двух разборных устройств.

Так что единственное, что вы можете сделать, это попытаться написать его немного чище:

def beSameJson(data: String) = 
    equalTo(OK) ^^ {status(_: Future[Result])} 
    and beSome.which(_ == "application/json") ^^ {contentType(_: Future[Result])} 
    and be_==(other) ^^ {contentAsJson(_: Future[Result])} 

Если вам нужно разложить ответы чаще, вы можете попробовать сделать это более обобщенно

object Dummy extends Matcher[Any] { 
    def apply[S <: Any](s: Expectable[S]) = { 
    result(true, 
     s.description + " is ignored", 
     s.description + " is ignored", 
     s) 
    } 
} 

def beResponseWhere(json: Matcher[JsValue] = Dummy, stat: Matcher[Int] = Dummy, tpe: Matcher[Option[String]] = Dummy) = 
    stat ^^ {status(_: Future[Result])} 
    and tpe ^^ {contentType(_: Future[Result])} 
    and json ^^ {contentAsJson(_: Future[Result])} 
} 

Возможно, вы должны использовать более удобные имена параметров (я попытался избежать конфликта с методами из вашего контекста для этого примера) и получить более полную информацию о доступных атрибутах.

Теперь вы должны быть в состоянии написать что-то вроде этого:

response must beResponseWhere(
    json = equalTo(expected), 
    tpe = beSome.which(_ == "application/json"), 
    stat = equalTo(OK) 
) 

DummyMatcher позволяет оставить некоторые части из. Я, очевидно, не пробовал этот код, так как у меня нет полной настройки. Я также должен был угадать некоторые типы, которые не ясны из вашего фрагмента кода.

+0

Это довольно близко к работе, но 'beSome.which (_ ==" application/json ") ^^ {contentType (_: Future [Result])}' не работает. contentType() возвращает параметр [String], и по какой-то причине я не понимаю, там есть несоответствие типа. Я исправил его, заменив 'be _ == (Some (" application/json ")) ^^ {contentType (_: Future [Result])}'. Во всяком случае, спасибо. Это выглядит намного лучше, чем то, что я делаю. –

+1

На самом деле, глядя на документацию, что-то подобное должно работать: beSome (beEqualTo ("foo")), поскольку beSome (...) может принимать совпадение в качестве аргумента. – dth

Смежные вопросы