I'm trying to do unit test for the following couchbase method call, I couldn't find a satisfactory sample here in SO, so I thought I'd post a question....
def getUserSession(token: String, ipAddr: String, userAgent: Option[String]): Future[Option[UserSession]] = {
val query = new Query().setIncludeDocs(true).setLimit(1)
.setRangeStart(ComplexKey.of(token))
.setRangeEnd(ComplexKey.of(s"$token\uefff"))
.setStale(Stale.FALSE)
bucket.find[UserSession](DOC_NAME, VIEW_BY_TOKEN)(query).map(_.headOption) map {
userSessionOpt => {
userSessionOpt filter {
userSession =>
(userSession.ipAddr == ipAddr) &&
(!userAgent.isDefined || !userSession.userAgent.isDefined || userSession.userAgent == userAgent)
}
}
}
}
So this is my attempt, my unit test excerpt:
val mockQueryResult = mock[Future[List[UserSession]]]
val mockUserSessionList = mock[List[UserSession]]
val mockUserSession = mock[UserSession]
// This is just my trial and erros
mockUserSessionList.head returns mockUserSession
mockUserSessionList(0) returns mockUserSession
Await.result(mockQueryResult, Duration(60, SECONDS)) returns mockUserSessionList
mockBucket.find[UserSession](any[String], any[String])(any[Query])(any[Reads[UserSession]], any[ExecutionContext]) returns mockQueryResult
val queryCaptor = capture[Query]
val readsCaptor = capture[Reads[UserSession]]
val executionContextCaptor = capture[ExecutionContext]
val docNameCaptor = capture[String]
val viewNameCaptor = capture[String]
userSessionRepositoryWithMockBucket.getUserSession(TEST_SESSION_TOKEN1, TEST_IP_ADDR1, TEST_USER_AGENT)
there was one(mockBucket).find[UserSession](docNameCaptor, viewNameCaptor)(queryCaptor)(readsCaptor, executionContextCaptor)
Now at some point in the bucket.find
method call is throwing NPE. I did a little digging and it seems like the Await.result
returns mocking doesn't really work in returning value for map
probably for obvious reasons. It does return result if I modified my getUserSession function to use Await.result
. I was just trying it out 'cause I haven't creatively figured out other ways (this is new to me).
There seems to be a less verbose ways of doing the mocking instead of having to do all the layers of Future[List[UserSession]]
. Thanks for your time!
I think I might've found the answer to how to mock future that work with map operation. Seems like if we create a 'successful' Future, it will work as follows:
val mockUserSession = createTestUserSession
val mockUserSessionList = mock[List[UserSession]]
val mockUserSessionListFuture = Future.successful[List[UserSession]](mockUserSessionList)
mockUserSessionList.headOption returns Some(mockUserSession)
This will in turn allows the map to in the getUserSession
to be supplied with proper instance of the headOption
which in this case is Some(mockUserSession)