FakeRequest кажется нулевым, когда передается контроллеру в модульном тесте - PullRequest
0 голосов
/ 08 июня 2018

Получение Null Pointer Ошибка при модульном тестировании контроллера.Кажется, проблема в строке

def signupUser = Action.async{
    implicit request => { //requeust seem to be null

Я так подозреваю, потому что трассировка стека из предыдущих тестов указывает на неявную строку запроса.Но я не знаю, что может быть не так в этом, потому что я использую FakeRequest, вот так val request = FakeRequest("POST", "/ws/users/signup").withJsonBody(Json.parse("""{"bad": "field"}"""))

Ниже приведен фрагмент контроллера, который я хочу протестировать

  class UserController @Inject()(userRepo: UsersRepository,cc: ControllerComponents, silhouette: Silhouette[JWTEnv])(implicit exec: ExecutionContext) extends AbstractController(cc){ 

def signupUser = Action.async{
    implicit request => {...}
 }

Я только хочу проверить, что контроллер возвращает ошибку, когда он получает запрос без json тела.Таким образом, мне не нужно Silhouette, и я хочу издеваться над этим.Но я получаю ошибку нулевого указателя.

Ниже описан способ написания моего модульного теста:

class UserControllerUnitSpec extends PlaySpec with MockitoSugar {

  "User signup request with non-JSON body" should {

    "return  400 (Bad Request) and the validation text 'Incorrect body type. Body type must be JSON'" in {

      val email = "d@d.com"
      val loginInfo = LoginInfo(CredentialsProvider.ID, email);
      val passwordInfo = PasswordInfo("someHasher","somePassword",Some("someSalt"))
      val internalUserProfile = InternalUserProfile(loginInfo,true,Some(passwordInfo))
      val externalUserProfile = ExternalUserProfile(email,"d","d",Some("somePassword"))
      val userProfile = UserProfile(Some(internalUserProfile),externalUserProfile)
      val user = User(UUID.randomUUID(),userProfile)

      println("testing with mocked User value",user);

      val mockUserRepository = mock[UsersRepository]
      when(mockUserRepository.findUser(loginInfo)).thenReturn(Future(Some(user)))
      when(mockUserRepository.saveUser(user)).thenReturn(Future(Some(user)))

      val mockSilhouette = mock[Silhouette[JWTEnv]] //I am probably not doing this correctly
      val mockControllerComponents = mock[ControllerComponents] //I am not sure if this is correct either
      val controller = new UserController(mockUserRepository,mockControllerComponents,mockSilhouette)

      val result:Future[Result] = controller.signupUser(FakeRequest())
      (result.map(response => {
        println("response: ",response)
        response mustBe BadRequest
      }))
    }
  }
}

Ответы [ 2 ]

0 голосов
/ 01 декабря 2018

(Выложено решение от имени автора вопроса) .

Вот ответ, который сработал.Спасибо Марио.

class UserControllerUnitSpec extends PlaySpec /*with MockitoSugar*/ {

  "User signup request with non-JSON body" should {

    "return  400 (Bad Request) and the validation text 'Incorrect body type. Body type must be JSON'" in {

      val email = "d@d.com"
      val loginInfo = LoginInfo(CredentialsProvider.ID, email);
      val passwordInfo = PasswordInfo("someHasher","somePassword",Some("someSalt"))
      val internalUserProfile = InternalUserProfile(loginInfo,true,Some(passwordInfo))
      val externalUserProfile = ExternalUserProfile(email,"d","d",Some("somePassword"))
      val userProfile = UserProfile(Some(internalUserProfile),externalUserProfile)
      val user = User(UUID.randomUUID(),userProfile)

      println("testing with mocked User value",user);

      val mockUserRepository = mock(classOf[UsersRepository])
      // when(mockUserRepository.findUser(loginInfo)).thenReturn(Future(Some(user)))
     // when(mockUserRepository.saveUser(user)).thenReturn(Future(Some(user)))

     // val mockSilhouette = mock(classOf[Silhouette[JWTEnv]])
      val mockControllerComponents = Helpers.stubControllerComponents()//mock(classOf[ControllerComponents])
      /*
      The controller needs Silhouette. Using Silhouette's test kit to create fake instances.
      If you would like to test this controller, you must provide an environment that can handle your Identity and Authenticator implementation.
      For this case Silhouette provides a FakeEnvironment which automatically sets up all components needed to test your specific actions.

      You must only specify one or more LoginInfo -> Identity pairs that should be returned by calling request.identity in your action and
      the authenticator instance that tracks this user.
       */

      //User extends Identity trait
      /*
      Under the hood, the environment instantiates a FakeIdentityService which stores your given identities and returns it if needed.
      It instantiates also the appropriate AuthenticatorService based on your defined Authenticator type. All Authenticator services are real
      service instances set up with their default values and dependencies.
       */
      implicit val sys = ActorSystem("MyTest")
      implicit val mat = ActorMaterializer()
      implicit val env = FakeEnvironment[JWTEnv](Seq(loginInfo->user))
      val defaultParser = new mvc.BodyParsers.Default()
      val securedAction = new DefaultSecuredAction(new DefaultSecuredRequestHandler(new DefaultSecuredErrorHandler(stubMessagesApi())),defaultParser)
      val unsecuredAction = new DefaultUnsecuredAction(new DefaultUnsecuredRequestHandler(new DefaultUnsecuredErrorHandler(stubMessagesApi())),defaultParser)
      val userAware = new DefaultUserAwareAction(new DefaultUserAwareRequestHandler(),defaultParser)
      val mockSilhouette = new SilhouetteProvider[JWTEnv](env,securedAction,unsecuredAction,userAware)

      val controller = new UserController(mockUserRepository,mockControllerComponents,mockSilhouette)

      val request = FakeRequest("POST","ws/users/signup")
      println("sending request",request)
      //val result = controller.someMethod()
      val result:Future[Result] = controller.signupUser(request)

      status(result) mustBe BAD_REQUEST

    }
  }
}
0 голосов
/ 09 июня 2018

Относительно mockControllerComponents, Helpers.stubControllerComponents можно использовать вместо макета:

val mockControllerComponents = Helpers.stubControllerComponents()

Относительно mockSilhouette, вы должны настроить макет, используя when(...).thenReturn(...) аналогичнокак вы сделали это для mockUserRepository, то есть проверьте все случаи использования silhouette внутри signupUser и предоставьте соответствующие заглушки метода:

val mockSilhouette = mock[Silhouette[JWTEnv]]
when(mockSilhouette.foo(...)).thenReturn(...)
when(mockUserRepository.bar(...)).thenReturn(...)
...
...