如何在playframework中设置数据库/ fixture以进行功能测试

问题描述 投票:1回答:2

我正在尝试测试我的Controller - Secure.java。我使用play的Fixtures类来设置数据库。不幸的是,当发出POST调用并且调用控件的方法时,数据库变为空。但是,在测试方法中,我可以按预期检索数据。

路线

POST    /login                                      user.Secure.authenticate

控制器Secure.java:

package controllers.user;

import java.io.File;
import java.io.FileOutputStream;
import java.io.PrintStream;
import java.lang.reflect.InvocationTargetException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.List;
import java.util.Date;
import java.util.TimeZone;

import models.User;
import play.Logger;
import play.Play;
import play.data.validation.Required;
import play.libs.Crypto;
import play.mvc.Controller;
import play.mvc.Http;
import play.mvc.Util;
import play.utils.Java;
import mashpan.crawl.dropbox.DropboxCrawler;
import mashpan.security.Check;
import mashpan.utilities.*;

import controllers.Application;

/**
 * a more or less exact copy of the secure implementation of play.
 * - enhanced with a transport guarantee.
 * - support for user authentification
 * 
 *  @author ra and Philip De Smedt
 *  @version 0.1
 *  @date 20/11/2011
 *
 */
public class Secure extends TransportUriGuaranteeController {

    public static void authenticate(@Required String username, String password, boolean remember) throws Throwable {
        Logger.debug("[Secure] authenticate: "
                + "[username=" + (username == null ? "null" : username.toString()) + "]"
                + "[password=" + (password == null ? "null" : password.toString()) + "]"
                + "[remember=" + remember + "]"
                );

        // Check tokens
        Boolean allowed = false;
        User user = User.find("byEmail", username).first();
        Logger.debug("[Secure.authenticate] "+"[user=" + (user == null ? "null" : user.toString()) + "]");
//      try {
//          // This is the deprecated method name
//          allowed = (Boolean)Security.invoke("authentify", username, password);
//      } 
//      catch (UnsupportedOperationException e ) 
//      {
//          // This is the official method name
//          allowed = (Boolean)Security.invoke("authenticate", username, password);
//      }

        allowed = Security.authenticate(username, password);


        if(validation.hasErrors() || !allowed) {
            Logger.debug("[Secure] Authentication failed"
                    + ", validationhasErrors()=" + validation.hasErrors()
                    + ", allowed="+allowed
                    );
            if(validation.hasErrors()) {
                Logger.debug("[Secure] validation has errors!");
                for(play.data.validation.Error e : validation.errors()) {
                    Logger.debug("[Secure] Error: "+"[e=" + (e == null ? "null" : e.toString()) + "]");
                }
            }
            flash.keep("url");
            flash.error("secure.error");
            params.flash();
            Application.index();
        }

        // Mark user as connected
        session.put("email", username);

        // Remember if needed
        if (remember) 
        {
            response.setCookie("rememberme", Crypto.sign(username) + "-" + username, "30d");
        }

        // Save last login time and redirect to the original URL (or /)
        User u = User.find("byEmail", username).first();
        u.lastLogin = new Date();
        u.save();

        Logger.debug("[Secure] Successfully authenticated user. Redirecting...");
        redirectToOriginalURL();
    }


    public static class Security extends Controller {

        /**
        * Extend Play!s security mechanism to authenticate against
        * the User object.
        */
        public static boolean authenticate(String email, String password) {
            Logger.debug("[Secure.Security.authenticate] "
                    + "[email=" + (email == null ? "null" : email.toString()) + "]"
                    + "[password=" + (password == null ? "null" : password.toString()) + "]");

            User user = User.find("byEmail", email).first();
            List<User> users = User.<User>findAll();
            Logger.debug("[Secure.Security] # of users found="+users.size());
            for(User u : users) {
                Logger.debug("[Secure.Security] "+"[u=" + (u == null ? "null" : u.toString()) + "]");
            }

            if (user == null) {
                Logger.debug("[Secure.Security] Could not find user, authentication failed!");
                return false;
            }

            if (user.confirmationCode.length() != 0) { //user not confirmed yet
                Logger.debug("[Secure.Security] User not confirmed yet, authentication failed!");
                return false;
            }
            return user.isThisCorrectUserPassword(password);
        }

        public static boolean check(String check) {
            if ("isConnected".equals(check)) {
                return Security.isConnected();                  
            }
            return false;
        }

        /**
        * This method returns the current connected username
        * @return
        */
        public static String connected() {
            return session.get("email");
        }

        /**
        * Indicate if a user is currently connected
        * @return  true if the user is connected
        */
        public static boolean isConnected() {
            return session.contains("email");
        }

        /**
        * This method is called after a successful authentication.
        * You need to override this method if you with to perform specific actions (eg. Record the time the user signed in)
        */
        static void onAuthenticated() { }

        /**
        * This method is called before a user tries to sign off.
        * You need to override this method if you wish to perform specific actions (eg. Record the name of the user who signed off)
        */
        static void onDisconnect() { }

        /**
        * This method is called after a successful sign off.
        * You need to override this method if you wish to perform specific actions (eg. Record the time the user signed off)
        */
        static void onDisconnected() { }

        /**
        * This method is called if a check does not succeed. By default it shows the not allowed page (the controller forbidden method).
        * @param profile
        */
        static void onCheckFailed(String profile) {
            forbidden();
        }
    }
}

测试类SecureTest.java

package controller.user;

import java.util.*;

import mashpan.utilities.*;
import models.*;

import org.junit.*;

import play.*;
import play.cache.*;
import play.db.jpa.GenericModel.JPAQuery;
import play.mvc.Http.Response;
import play.test.*;

public class FunctionalSecureTests extends FunctionalTest {
    @Before
    public void setUp() {
        Fixtures.deleteDatabase();
        Fixtures.loadModels("testusers.yaml");
        Cache.clear();
    }


    @Test
    public void postLogin_shouldHaveStatus200() {
        User user = User.find("byEmail", UserUtility.EMAIL).first();
        Logger.debug("[FunctionalSecureTests] "+"[user=" + (user == null ? "null" : user.toString()) + "]"); //prints out


        Map<String, String> parameters = new HashMap<String, String>();
        parameters.put("username", UserUtility.EMAIL);
        parameters.put("password", UserUtility.PASSWORD);

        Response response = POST("/login", parameters);

        assertIsOk(response);
        assertStatus(200, response);
    }

}

CONF / testusers.yaml

User(mashpan):
  first_name: "Mash"
  last_name: "Pan"
  email: "[email protected]"
  signupDate: 2012-03-08
  passwordHash: "NOTFORYOU"
  isAdmin: No
  confirmationCode: ""
  activationSent: Yes
  recoverPasswordCode: !!null
  lastLogin: !!null
  referralCode: !!null

堆栈跟踪

   DEBUG 232 :play#debug - [FunctionalSecureTests] [user=User [first_name=Mash, last_name=Pan, [email protected], signupDate=2012-03-08 01:00:00.0, passwordHash=$2a$10$L6IdeDhMGe1T7IbtSDd.6uLOvhHk7IoAzRzGzNlk8Cm4WWyWCbIp., isAdmin=false, confirmationCode=, activationSent=true, recoverPasswordCode=null, lastLogin=null, referralCode=null, [id=1]]]
   DEBUG 232 :play#debug - [Secure] authenticate: [[email protected]][password=chickenrunfasteriffedup][remember=false]
   DEBUG 232 :play#debug - [Secure.authenticate] [user=null]
   DEBUG 232 :play#debug - [Secure.Security.authenticate] [[email protected]][password=chickenrunfasteriffedup]
   DEBUG 232 :play#debug - [Secure.Security] # of users found=0
   DEBUG 232 :play#debug - [Secure.Security] Could not find user, authentication failed!
   DEBUG 232 :play#debug - [Secure] Authentication failed, validationhasErrors()=false, allowed=false
playframework fixtures
2个回答
5
投票

您的功能测试在一个将在测试结束时结束的事务中运行。因此,在测试完成之前,您在此事务中执行的所有操作都不会提交到数据库。因此,在这种情况下,您可以使用作业仅为设置创建新事务

@Before
public void setUp() throws Exception {
    new Job() {
        @Override
        public void doJob() throws Exception {
            Fixtures.deleteDatabase();
            Fixtures.loadModels("testusers.yaml");
            Cache.clear();
        }
    }.now().get();
}

0
投票

只需添加:

JPA.em().getTransaction().commit();

Fixtures.loadModels之后。

© www.soinside.com 2019 - 2024. All rights reserved.