私はMockitoを使って一般的な方法を模擬しようとしています。私が模倣しようとしている方法は、汎用タイプT
に対してReaderT
を作成し、Output
タイプを汎用タイプT
に変換する暗黙の変換も利用できると考えています。暗黙の汎用型への変換を期待する関数を模擬してください
実装は重要ではありませんが、ここではこの方法自体の削減です:
/**
* The return type of WebReaderT is held within the class scope.
* It pre-populates some of the types for ReaderT.
*/
def createToken[T](authRequest: Input, tokenTtl: TokenTtlConfig)(implicit f: Output => T): WebReaderT[T]
私はからかったときしかし、私はエラーを受信しています、APIを実行するときにそれを期待するような方法で動作します私のテストの中でそれを実行します。私はモックの数回の反復を経てきたし、これは私が現在持っているものです。
when(mock.createToken[Any](any[AuthAdapter.Input], any[TokenTtlConfig])(any[AuthAdapter.Output => Any])) thenAnswer { invocation =>
val tokenTtl = invocation.getArgument[TokenTtlConfig](1)
tokenTtl match {
case config.tokenTtlMap.v0Tokens => mockCreateToken[LoginResponse](tokenTtl)
case config.tokenTtlMap.v1Tokens => mockCreateToken[AccessTokenResponse](tokenTtl)
}
}
/**
* This method is functionally a direct copy of the method that
* it's effectively mocking.
*/
def mockCreateToken[T](tokenTtl: TokenTtlConfig)(implicit f: AuthAdapter.Output => T): WebReaderT[T] = {
ReaderT.lift[EitherTError, SentinelEnv[Future], T](EitherT.fromEither[Future](Right(AuthAdapter.Output(
mockUser1._id,
mockUser1._id,
tokenTtl.accessTtl.map(AccessToken(DateTime.now, _, "foo")),
tokenTtl.refreshTtl.map(RefreshToken(DateTime.now, _, "bar"))
))))
}
私は(私の知識から)モック自体でT
、たとえば、のワイルドカード型を持つことができないだからAny
と一致させてから、tokenTtl
を既知の値のセットに一致させることによって、予想される出力タイプを決定する必要があります。これは明らかに、私が出力タイプを決定するためにはかなり疑わしい方法です。アプリケーションが内部でconfig.tokenTtlMap.<?>
値を現在使用していることに大きく依存しているためです。このモック実装は限り明確に行くための最良の方法ですが、
// Only match "LoginResponse"
when(mockAuthAdapter.createToken[LoginResponse](any[AuthAdapter.Input], any[TokenTtlConfig])(any[AuthAdapter.Output => LoginResponse])) thenAnswer { invocation =>
mockCreateToken[LoginResponse](invocation.getArgument[TokenTtlConfig](1))
}
// Only match "AccessTokenResponse"
when(mockAuthAdapter.createToken[AccessTokenResponse](any[AuthAdapter.Input], any[TokenTtlConfig])(any[AuthAdapter.Output => AccessTokenResponse])) thenAnswer { invocation =>
mockCreateToken[AccessTokenResponse](invocation.getArgument[TokenTtlConfig](1))
}
:私はMockitoは、このような一般的なメソッドに渡されるタイプを一致させることができたことを期待したい。この貧しいアプローチを避けるために
私は、Mockitoは最初のモックを無視するだけです(2番目のモックをオーバーライドしますか?)ので、汎用メソッドに渡される予想される出力タイプと正しく一致しません。私は非常にある任意の助けをいただければと思います
[ERROR] [12/13/2017 14:42:05.587] [specs2.fixed.env-1062542254-1] [akka.actor.ActorSystemImpl(io-ctek-services-sentinel-routes-v0-TokensRouteSpec)] Error during processing of request: 'java.lang.NullPointerException (No error message supplied)'. Completing with 500 Internal Server Error response. To change default exception handling behavior, provide a custom ExceptionHandler.
java.lang.NullPointerException
at cats.data.EitherTFunctions$FromEitherPartiallyApplied.apply(EitherT.scala:277)
at io.ctek.services.sentinel.helpers.RouteHelpers$.createToken(RouteHelpers.scala:49)
at io.ctek.services.sentinel.helpers.RouteHelpers$.$anonfun$new$1(RouteHelpers.scala:43)
at org.mockito.internal.stubbing.StubbedInvocationMatcher.answer(StubbedInvocationMatcher.java:35)
at org.mockito.internal.handler.MockHandlerImpl.handle(MockHandlerImpl.java:95)
at org.mockito.internal.handler.NullResultGuardian.handle(NullResultGuardian.java:32)
at org.mockito.internal.handler.InvocationNotifierHandler.handle(InvocationNotifierHandler.java:36)
at org.mockito.internal.creation.bytebuddy.MockMethodInterceptor.doIntercept(MockMethodInterceptor.java:57)
at org.mockito.internal.creation.bytebuddy.MockMethodInterceptor.doIntercept(MockMethodInterceptor.java:43)
at org.mockito.internal.creation.bytebuddy.MockMethodInterceptor$DispatcherDefaultingToRealMethod.interceptSuperCallable(MockMethodInterceptor.java:119)
フルエラーがこのPasteBin
で見つけることができます:私の最善の努力にもかかわらず
、両方の実装は、このようなNullPointerException
につながりますこの問題を解決する!