如何为Playframework中的功能测试设置数据库/夹具 [英] how to setup database/fixture for functional tests in playframework

查看:87
本文介绍了如何为Playframework中的功能测试设置数据库/夹具的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在测试我的控制器-Secure.java.我使用play的Fixtures类来设置数据库.不幸的是,在发出POST调用和调用控件的方法的情况下,数据库原来是空的.但是,在测试方法内部,我可以按预期检索数据.

I am trying to test my Controller - Secure.java. I use play's Fixtures class to setup the database. Unfortunately as the POST call is issued and the control's method is called the database turns out to be empty. However, inside the test-method I can retrieve the data as expected.

路线

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

conf/testusers.yaml

User(mashpan):
  first_name: "Mash"
  last_name: "Pan"
  email: "tester@gmail.com"
  signupDate: 2012-03-08
  passwordHash: "NOTFORYOU"
  isAdmin: No
  confirmationCode: ""
  activationSent: Yes
  recoverPasswordCode: !!null
  lastLogin: !!null
  referralCode: !!null

stacktrace

stacktrace

   DEBUG 232 :play#debug - [FunctionalSecureTests] [user=User [first_name=Mash, last_name=Pan, email=mashpantester@gmail.com, 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: [username=mashpantester@gmail.com][password=chickenrunfasteriffedup][remember=false]
   DEBUG 232 :play#debug - [Secure.authenticate] [user=null]
   DEBUG 232 :play#debug - [Secure.Security.authenticate] [email=mashpantester@gmail.com][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

推荐答案

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

Your functional test run in a transaction that will end at the end of the test. So everything you do in this transaction won't be commited to the database until the test is finished. So in this case you can use a job to create a new transaction only for the setup

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

这篇关于如何为Playframework中的功能测试设置数据库/夹具的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆