1

という名前のコントローラー メソッドをテストしたいと思います。このメソッドauthenticate()は非常に単純なロジックを持ちます。リクエストから検証emailpassword、結果を JSON として返します。

public class Users extends Controller {

    static Form<User> userForm = Form.form(User.class);

    public static Result login() {
        return ok(views.html.users.login.render(userForm));
    }

    public static Result authenticate() {
        Form<User> filledForm = userForm.bindFromRequest();
        if (filledForm.hasErrors()) {
            return badRequest(views.html.users.login.render(filledForm));
        } else {
            ObjectNode result = Json.newObject();
            User u = filledForm.get();
            if (User.isAuthValid(u.email, u.password))
                result.put("status", "OK");
            else
                result.put("status", "Authentication failed");
            return ok(result);
        }
    }
}

のテスト コードは次のauthenticate()とおりです。

@Test
public void callAuthenticate() {
    Map<String, String> formData = Maps.newHashMap();
    formData.put("email", "aaa@bbb.com");
    formData.put("password", "password");

    Result result = callAction(controllers.routes.ref.Users.authenticate(),
            fakeRequest().withFormUrlEncodedBody(formData));
    assertThat(status(result)).isEqualTo(Http.Status.OK);
}

しかし、次のスタックトレースでエラーが発生しました:

javax.validation.ValidationException: HV000041: Call to TraversableResolver.isReachable() threw an exception.
    at org.hibernate.validator.internal.engine.ValidatorImpl.isValidationRequired(ValidatorImpl.java:1230)
    at org.hibernate.validator.internal.engine.ValidatorImpl.validateConstraint(ValidatorImpl.java:438)
    at org.hibernate.validator.internal.engine.ValidatorImpl.validateConstraintsForDefaultGroup(ValidatorImpl.java:387)
    at org.hibernate.validator.internal.engine.ValidatorImpl.validateConstraintsForCurrentGroup(ValidatorImpl.java:351)
    at org.hibernate.validator.internal.engine.ValidatorImpl.validateInContext(ValidatorImpl.java:303)
    at org.hibernate.validator.internal.engine.ValidatorImpl.validate(ValidatorImpl.java:133)
    at org.springframework.validation.beanvalidation.SpringValidatorAdapter.validate(SpringValidatorAdapter.java:194)
    at play.data.Form.bind(Form.java:327)
    at play.data.Form.bindFromRequest(Form.java:215)
    at controllers.Users.authenticate(Users.java:50)
    at controllers.ref.ReverseUsers$$anonfun$authenticate$1.apply(routes_reverseRouting.scala:477)
    at controllers.ref.ReverseUsers$$anonfun$authenticate$1.apply(routes_reverseRouting.scala:477)
    at play.core.Router$HandlerInvoker$$anon$6$$anon$2.invocation(Router.scala:164)
    at play.core.j.JavaAction$$anon$1.call(JavaAction.scala:31)
    at play.core.j.JavaAction$$anon$2.apply(JavaAction.scala:74)
    at play.core.j.JavaAction$$anon$2.apply(JavaAction.scala:73)
    at play.libs.F$Promise$PromiseActor.onReceive(F.java:420)
    at akka.actor.UntypedActor$$anonfun$receive$1.applyOrElse(UntypedActor.scala:159)
    at akka.actor.ActorCell.receiveMessage(ActorCell.scala:425)
    at akka.actor.ActorCell.invoke(ActorCell.scala:386)
    at akka.dispatch.Mailbox.processMailbox(Mailbox.scala:230)
    at akka.dispatch.Mailbox.run(Mailbox.scala:212)
    at akka.dispatch.ForkJoinExecutorConfigurator$MailboxExecutionTask.exec(AbstractDispatcher.scala:502)
    at scala.concurrent.forkjoin.ForkJoinTask.doExec(ForkJoinTask.java:262)
    at scala.concurrent.forkjoin.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:975)
    at scala.concurrent.forkjoin.ForkJoinPool.runWorker(ForkJoinPool.java:1478)
    at scala.concurrent.forkjoin.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:104)
Caused by: org.springframework.beans.InvalidPropertyException: Invalid property 'email' of bean class [models.User]: No property 'email' found
    at org.springframework.beans.BeanWrapperImpl.getPropertyDescriptor(BeanWrapperImpl.java:337)
    at play.db.ebean.Model._idAccessors(Model.java:47)
    at play.db.ebean.Model._getId(Model.java:67)
    at play.db.ebean.Model.hashCode(Model.java:208)
    at org.hibernate.validator.internal.engine.resolver.SingleThreadCachedTraversableResolver$TraversableHolder.buildHashCode(SingleThreadCachedTraversableResolver.java:153)
    at org.hibernate.validator.internal.engine.resolver.SingleThreadCachedTraversableResolver$TraversableHolder.<init>(SingleThreadCachedTraversableResolver.java:114)
    at org.hibernate.validator.internal.engine.resolver.SingleThreadCachedTraversableResolver$TraversableHolder.<init>(SingleThreadCachedTraversableResolver.java:96)
    at org.hibernate.validator.internal.engine.resolver.SingleThreadCachedTraversableResolver.isReachable(SingleThreadCachedTraversableResolver.java:41)
    at org.hibernate.validator.internal.engine.ValidatorImpl.isValidationRequired(ValidatorImpl.java:1221)
    ... 26 more

ブラウザでテストすると、期待どおりに機能しました。しかし、JUnit テストのみが で失敗しInvalidPropertyExceptionます。テスト コードの何が問題になっていますか?

参考までに、モデルは次のUserとおりです。

@Entity
public class User extends Model {

    @Id
    @Required
    @NonEmpty
    public String email;

    public String nickname;

    @Required
    public String password;

    public String salt;

    public static Finder<String, User> find = new Finder<String, User>(
            String.class, User.class);

    public static User findByEmail(String email) {
        return find.where().eq("email", email).findUnique();
    }

    public static boolean isAuthValid(String email, String password) {
        User user = findByEmail(email);
        if (user == null)
            return false;

        return user.isValidPassword(password);
    }

    public boolean isValidPassword(String password) {
        return this.password.equals(DigestUtils.md5Hex(password + this.salt));
    }

}

アドバイス/修正をありがとう。

4

1 に答える 1

1

バインディングが機能するように、「偽の」アプリケーション内でテストを実行する必要があります。したがって、テストは次のようになります。

@Test
public void callAuthenticate() {
    running(fakeApplication(), new Runnable() {
        public void run() {
            Map<String, String> formData = Maps.newHashMap();
            formData.put("email", "aaa@bbb.com");
            formData.put("password", "password");

            Result result = callAction(controllers.routes.ref.Users.authenticate(),
            fakeRequest().withFormUrlEncodedBody(formData));
            assertThat(status(result)).isEqualTo(Http.Status.OK);
        }
    }
}
于 2013-05-10T08:28:48.570 に答える