У меня простой REST-API.У каждого подпути api есть своя собственная реализация сервиса.
Вопрос: как правильно его проверить?
Пример:
class RestAPI(implicit dispatcher: ExecutionContext) // some services need its own dispatcher
extends FirstService with SecondService with etc... {
val api: Route = pathPrefix("api") {
get {
firstService()
} ~ post {
secondService()
} ~ ...
}
def start(implicit system: ActorSystem, materializer: ActorMaterializer): Unit = {
Http().bindAndHandle(api, "host", 8080)
}
}
object RestAPI {
def apply(implicit dispatcher: ExecutionContext): RestAPI = new RestAPI
}
В этом случае я не могу проверитьмоя конечная точка из-за зависимости контекста исполнения и реализации сервиса, которую я должен издеваться.Я могу создать свою собственную реализацию RestApi в тестовом примере, но мне приходится обновлять ее каждый раз, когда что-то меняется внутри реального RestApi
Я пробовал другой способ:
class RestAPI(implicit dispatcher: ExecutionContext) { // some services need its own dispatcher
this: FirstService with SecondService with etc... =>
val api: Route = pathPrefix("api") {
get {
firstService()
} ~ post {
secondService()
} ~ ...
}
def start(implicit system: ActorSystem, materializer: ActorMaterializer): Unit = {
Http().bindAndHandle(api, "host", 8080)
}
}
object RestAPI {
def apply(implicit dispatcher: ExecutionContext): RestAPI = new RestAPI extends DefaultFirstService with DefaultSecondService with etc...
}
Test {
val api = (new RestApi(dispatcher) extends StubOne with StubTwo with ...).api
}
В этом случаепо крайней мере, я могу проверить все конечные точки, но мне нужно пройти контекст выполнения и построить объект RestApi, прежде чем я смогу получить свои маршруты.Кроме того, это не лучшее решение, потому что сейчас мне нужно написать new RestApi(dispatcher) extends StubOne with StubTwo with ...
, и если есть 1 или 2 службы - это нормально, но если их больше 3, это выглядит немного неловко (по моему мнению).
Тогда я попробовал этот подход:
class RestAPI(serviceOne: FirstService, serviceTwo: SecondService, ...)(implicit dispatcher: ExecutionContext) { // some services need its own dispatcher
val api: Route = pathPrefix("api") {
get {
serviceOne.firstService()
} ~ post {
serviceTwo.secondService()
} ~ ...
}
def start(implicit system: ActorSystem, materializer: ActorMaterializer): Unit = {
Http().bindAndHandle(api, "host", 8080)
}
}
object RestAPI {
def apply(serviceOne: FirstService, serviceTwo: SecondService, ...)(implicit dispatcher: ExecutionContext): RestAPI = new RestAPI(serviceOne, serviceTwo, ...)
}
Test {
val api = (new RestApi(...)(dispatcher)).api
}
Вероятно, это наиболее распространенный подход, но мне все равно нужно передать контекст выполнения.
Итак, главный вопрос - как проверить мои конечные точки, которые зависят от реализации сервиса, но без реальной реализации этих сервисов?Я подозреваю, что есть проблема в дизайне реализации, но я все еще могу ее изменить.Вопрос в том, какой подход выбрать?