With longevity, you provide us with your domain model, and we give you back a longevity context. The longevity context contains your repositories. For example, let's say we are building a simple blogging application, and we have three kinds of persistent objects: users, blog posts, and blogs. We build our subdomain like so:
import longevity.subdomain._
val subdomain = Subdomain(
"blogging",
EntityTypePool(User, BlogPost, Blog))
For more details on what the User, Blog, and BlogPost classes and companion objects look like, please read about building your domain model in the user manual.
Now let's build our longevity context. We'll specify Cassandra as our back end:
import longevity.context.LongevityContext
import longevity.context.Cassandra
val context = LongevityContext(subdomain, Cassandra)
Now we can pull our standard set of repositories from there:
val repoPool = context.repoPool
The repo pool is a TypeKeyMap, which allows you to pull out repositories by aggregate type:
import longevity.persistence.Repo
val userRepo: Repo[User] = repoPool[User]
val blogRepo: Repo[Blog] = repoPool[Blog]
val blogPostRepo: Repo[BlogPost] = repoPool[BlogPost]
The repository API supports all the basic CRUD operations, as well as queries.
In our test suite, some of our tests will want to run against an actual Cassandra database, but using a test database, and not the production database. For these tests, the longevity context provides us an alternative set of repositories:
val testRepoPool = context.testRepoPool
val testUserRepo: Repo[User] = testRepoPool[User]
For tests in which you don't want to mock your repositories, but you want to avoid the overhead of a real database, longevity provides fully functional in-memory repositories:
val inMemUserRepo: Repo[User] =
context.inMemTestRepoPool[User]
Now let's exercise the repo CRUD operations - Repo.create, Repo.retrieve, Repo.update, and Repo.delete - against the test database. The longevity context provides you with a ScalaTest suite that does exactly that:
import scala.concurrent.ExecutionContext.Implicits.global
val crudSpec: org.scalatest.Suite =
longevityContext.repoCrudSpec
Typical ScalaTest execution usually scans for top-level classes, so we can embed our crudSpec in a top-level org.scalatest.Suites to get it to run as part of our test suite:
import org.scalatest.Suites
Running the BloggingCrudSpec will test the behavior of all the CRUD operations for all three of our aggregates, giving us assurance that the software and the database are properly integrated.
For more details on how this all works, please see the chapter on testing in the longevity user manual.
When we use an ORM or a database driver to do our persistence, we commonly dedicate an entire module of our test suite to assuring that the basic CRUD operations of our persistence layer work correctly when connecting to a real database. These tests are important, because getting our persistence layer to integrate with a real database is tricky and error-prone. But they are hard to write and maintain, representing a significant drain on productivity. Why not try a framework that does the hard work for you? We want you to focus your efforts on your domain and your business logic. We'll handle the persistence for you.
No comments:
Post a Comment
Note: Only a member of this blog may post a comment.