你如何模拟一个可以使用 map 函数的未来?
How do you mock a future that will work with map function?
我正在尝试为以下 couchbase 方法调用做单元测试,我在 SO 中找不到满意的示例,所以我想我 post 一个问题....
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)
}
}
}
}
所以这是我的尝试,我的单元测试摘录:
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)
现在 bucket.find
方法调用中的某个时刻抛出 NPE。我做了一点挖掘,似乎 Await.result
returns 模拟在 returning 值中并没有真正起作用 map
可能出于明显的原因。如果我将 getUserSession 函数修改为使用 Await.result
,它会产生 return 结果。我只是尝试一下,因为我还没有创造性地想出其他方法(这对我来说是新的)。
似乎有一种不那么冗长的方式来进行模拟,而不是必须完成 Future[List[UserSession]]
的所有层。感谢您的宝贵时间!
我想我可能已经找到了如何模拟与地图操作一起工作的未来的答案。看起来如果我们创建一个 'successful' Future,它将按如下方式工作:
val mockUserSession = createTestUserSession
val mockUserSessionList = mock[List[UserSession]]
val mockUserSessionListFuture = Future.successful[List[UserSession]](mockUserSessionList)
mockUserSessionList.headOption returns Some(mockUserSession)
这将反过来允许 getUserSession
中的地图提供 headOption
的正确实例,在本例中为 Some(mockUserSession)
我正在尝试为以下 couchbase 方法调用做单元测试,我在 SO 中找不到满意的示例,所以我想我 post 一个问题....
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)
}
}
}
}
所以这是我的尝试,我的单元测试摘录:
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)
现在 bucket.find
方法调用中的某个时刻抛出 NPE。我做了一点挖掘,似乎 Await.result
returns 模拟在 returning 值中并没有真正起作用 map
可能出于明显的原因。如果我将 getUserSession 函数修改为使用 Await.result
,它会产生 return 结果。我只是尝试一下,因为我还没有创造性地想出其他方法(这对我来说是新的)。
似乎有一种不那么冗长的方式来进行模拟,而不是必须完成 Future[List[UserSession]]
的所有层。感谢您的宝贵时间!
我想我可能已经找到了如何模拟与地图操作一起工作的未来的答案。看起来如果我们创建一个 'successful' Future,它将按如下方式工作:
val mockUserSession = createTestUserSession
val mockUserSessionList = mock[List[UserSession]]
val mockUserSessionListFuture = Future.successful[List[UserSession]](mockUserSessionList)
mockUserSessionList.headOption returns Some(mockUserSession)
这将反过来允许 getUserSession
中的地图提供 headOption
的正确实例,在本例中为 Some(mockUserSession)