nock - Nock is an HTTP mocking and expectations library for Node.js.
Nock can be used to test modules that perform HTTP requests in isolation.
For instance, if a module performs HTTP requests to a CouchDB server or makes HTTP requests to the Amazon API, you can test that module in isolation.
$ sbt clean publish-localBefore running the tests the first time, you must ensure the npm packages are installed:
$ npm installThen you can run the tests:
$ sbt testimport io.scalajs.npm.nock._
import scala.scalajs.js
val couchdb = Nock("http://myapp.iriscouch.com")
.get("/users/1")
.reply(200, js.Dictionary(
"_id" -> "123ABC",
"_rev" -> "946B7D1C",
"username" -> "pgte",
"email" -> "pedro.teixeira@gmail.com"
))Using a string:
import io.scalajs.nodejs.console
import io.scalajs.npm.nock._
import scala.scalajs.js
val scope = Nock("http://www.example.com")
.get("/resource")
.reply(200, "domain matched")
if (!scope.isDone()) {
console.info("active mocks: %j", scope.activeMocks())
console.info("pending mocks: %j", scope.pendingMocks())
}Using a RegExp:
import io.scalajs.nodejs.console
import io.scalajs.npm.nock._
import scala.scalajs.js
import scala.scalajs.js.RegExp
val scope = Nock(RegExp("/example\\.com/"))
.get("/resource")
.reply(200, "domain matched")
if (!scope.isDone()) {
console.info("active mocks: %j", scope.activeMocks())
console.info("pending mocks: %j", scope.pendingMocks())
}Using a function:
import io.scalajs.npm.nock._
val scope = Nock("http://www.example.com")
.get((uri: String) => uri.indexOf("cats") >= 0)
.reply(200, "path using function matched")You can specify the request body to be matched as the second argument to the get, post, put or delete specifications like this:
import io.scalajs.npm.nock._
import scala.scalajs.js
val scope = Nock("http://myapp.iriscouch.com")
.post("/users", js.Dictionary(
"username" -> "pgte",
"email" -> "pedro.teixeira@gmail.com"
))
.reply(201, js.Dictionary(
"ok" -> true,
"id" -> "123ABC",
"rev" -> "946B7D1C"
))By default every mocked request is expected to be made exactly once, and until it is it'll appear in scope.pendingMocks(), and scope.isDone() will return false (see expectations). In many cases this is fine, but in some (especially cross-test setup code) it's useful to be able to mock a request that may or may not happen. You can do this with optionally(). Optional requests are consumed just like normal ones once matched, but they do not appear in pendingMocks(), and isDone() will return true for scopes with only optional requests pending.
import io.scalajs.npm.nock._
import scala.scalajs.js
val example = Nock("http://example.com")
example.pendingMocks() // []
example.get("/pathA").reply(200)
example.pendingMocks() // ["GET http://example.com:80/path"]
// ...After a request to example.com/pathA:
example.pendingMocks() // []
example.get("/pathB").optionally().reply(200)
example.pendingMocks() // []If you need some request on the same host name to be mocked and some others to really go through the HTTP stack, you can use the allowUnmocked option like this:
import io.scalajs.npm.nock._
import scala.scalajs.js
val options = js.Dictionary("allowUnmocked" -> true)
val scope = Nock("http://my.existing.service.com", options)
.get("/my/url")
.reply(200, "OK!")
// GET /my/url => goes through nock
// GET /other/url => actually makes request to the server Bear in mind that, when applying {allowUnmocked: true} if the request is made to the real server, no interceptor is removed.
Nock understands query strings. Instead of placing the entire URL, you can specify the query part as an object:
import io.scalajs.npm.nock._
import scala.scalajs.js
import scala.scalajs.js.annotation.ScalaJSDefined
Nock("http://example.com")
.get("/users")
.query(new Person(name = "pedro", surname = "teixeira"))
.reply(200, new Items(results = js.Array(new Item(id = "pgte"))))
@ScalaJSDefined
class Person(val name: String, val surname: String) extends js.Object
@ScalaJSDefined
class Items(val results: js.Array[Item]) extends js.Object
@ScalaJSDefined
class Item(val id: String) extends js.ObjectNock supports array-style/object-style query parameters. The encoding format matches with request module.
import io.scalajs.npm.nock._
import scala.scalajs.js
Nock("http://example.com")
.get("/users")
.query(js.Dictionary(
"names" -> js.Array("alice", "bob"),
"tags" -> js.Dictionary(
"alice" -> js.Array("admin", "tester"),
"bob" -> js.Array("tester")
)))
.reply(200, js.Dictionary("results" -> js.Array(js.Dictionary("id" -> "pgte"))))import io.scalajs.npm.nock._
import scala.scalajs.js
Nock("http://www.google.com")
.get("/cat-poems")
.replyWithError(js.Dictionary("message" -> "something awful happened", "code" -> "AWFUL_ERROR"))To add the Nock binding to your project, add the following to your build.sbt:
libraryDependencies += "io.scalajs.npm" %%% "nock" % "0.4.1"Optionally, you may add the Sonatype Repository resolver:
resolvers += Resolver.sonatypeRepo("releases")