Embedded Servers and Apps

Finatra provides a way to run an embedded version of your service or app running locally on ephemeral ports. This allows you to run actual requests against an actual version of your server when testing.

The embedded utilities are also useful for testing and debugging your code when prototyping. If your service or API makes calls to other services, instead of mocking out or overriding those dependencies with dummy implementations you can always write a test using an Embedded version of your server which talks to real downstream services (of course you’d never want to commit a test like this to your source repository, especially if you run any type of continuous integration system). You’ll be able to run this test normally through the test runner of an IDE which would allow you to easily set breakpoints and step-through code for debugging. As opposed to needing to build and run your service locally and attach a remote debugger.

See:

../../_images/embedded.png

You’ll notice that this hierarchy generally follows the server trait hierarchy as c.t.finatra.http.HttpServer and c.t.finatra.thrift.ThriftServer extend from c.t.server.TwitterServer which extends from c.t.app.App.

Testing With Global Flags

The embedded servers and the embedded app allow for passing TwitterUtil Flags to the server under test via the flags constructor argument (a map of flag name to flag value) which is meant to mimic setting flag values via the command line.

However it is not recommended that users set any GlobalFlag value in this manner. In normal usage, the value of a GlobalFlag is only read once during the initialization of the JVM process.

If you wish to test with toggled values of a GlobalFlag you should prefer using Flag.let or Flag.letClear in tests instead of passing the GlobalFlag value via the flags arg of an embedded server or embedded app. For example,

import com.twitter.finatra.http.EmbeddedHttpServer
import com.twitter.finagle.http.Status
import com.twitter.inject.server.FeatureTest

class ExampleServerFeatureTest extends FeatureTest {
  override val server = new EmbeddedHttpServer(new ExampleServer)

  test("ExampleServer#perform feature") {

    someGlobalFlag.let("a value") {
      // any read of the `someGlobalFlag` value in this closure will be "a value"
      server.httpGet(
        path = "/",
        andExpect = Status.Ok)

      ???
    }
  }
}

See the scaladoc for c.t.app.Flag for more information on using Flag.let or Flag.letClear.

InMemoryStatsReceiver

The EmbeddedTwitterServer (and thus its subclasses: EmbeddedHttpServer and EmbeddedThriftServer) binds an instance of the com.twitter.finagle.stats.InMemoryStatsReceiver to the underlying server’s object graph (if the underlying server supports injection). This will override any other bound implementation of a c.t.finagle.stats.StatsReceiver in the server’s object graph.

The EmbeddedTwitterServer exposes the bound StatsReceiver along with helper methods for asserting counter, stat, and gauge values, such that you can expect behavior against the underlying server’s recorded stats in tests.

Feature Tests also print all recorded stats to stdout after each test by default.

See: c.t.finatra.multiserver.test.MultiServerFeatureTest for an example usage.