使用Securesocial注释保护的单元测试方法

时间:2013-10-07 13:24:45

标签: java unit-testing playframework playframework-2.1 securesocial

我正在尝试为使用Play 2.1.4和Socialsecure的web应用程序进行一些功能测试。在使用securesocial之前,这些测试非常直接,但现在我遇到了麻烦,想象一下我如何对安全行为进行测试。

@Test
public void createNewNote() {
    Result result;
    // Should return bad request if no data is given
    result = callAction(
            controllers.routes.ref.Notes.newNote(),
            fakeRequest().withFormUrlEncodedBody(
                    ImmutableMap.of("title", "", "text",
                            "")));
    assertThat(status(result)).isEqualTo(BAD_REQUEST);

    result = callAction(
            controllers.routes.ref.Notes.newNote(),
            fakeRequest().withFormUrlEncodedBody(
                    ImmutableMap.of("title", "My note title", "text",
                            "My note content")));

    // Should return redirect status if successful
    assertThat(status(result)).isEqualTo(SEE_OTHER);
    assertThat(redirectLocation(result)).isEqualTo("/notes");

    Note newNote = Note.find.where().eq("title", "My note title")
            .findUnique();

    // Should be saved to DB
    assertNotNull(newNote);
    assertEquals("My note title", newNote.title);
    assertEquals("My note content", newNote.text);
}

截至目前,我在测试yml文件中有一个用户:

- !!models.User
id: 1234567890
username: Pingu
provider: Twitter
firstName: Pingu
lastName: Pingusson
email: pingu@note.com
password: password

我的用户很直接......:

@Table(
    uniqueConstraints=
        @UniqueConstraint(columnNames={"username"}))
@Entity
public class User extends Model {

    private static final long serialVersionUID = 1L;

@Id
public String id;

public String provider;

public String firstName;

public String lastName;

public String email;

public String password;

@MinLength(5)
@MaxLength(20)
public String username;

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

public static User findById(String id) {
    return find.where().eq("id", id).findUnique();
}
public static User findByEmail(String email) {
    return find.where().eq("email", email).findUnique();
}
@Override
public String toString() {
    return this.id + " - " + this.firstName;
}

}

和UserService:

公共类UserService扩展了BaseUserService {

public UserService(Application application) {
    super(application);
}

@Override
public void doDeleteExpiredTokens() {
    if (Logger.isDebugEnabled()) {
        Logger.debug("deleteExpiredTokens...");
    }
    List<LocalToken> list = LocalToken.find.where().lt("expireAt", new DateTime().toString()).findList();
    for(LocalToken localToken : list) {
        localToken.delete();
    }
}

@Override
public void doDeleteToken(String uuid) {
    if (Logger.isDebugEnabled()) {
        Logger.debug("deleteToken...");
        Logger.debug(String.format("uuid = %s", uuid));
    }
    LocalToken localToken = LocalToken.find.byId(uuid);
    if(localToken != null) {
        localToken.delete();
    }
}

@Override
//public Identity doFind(UserId userId) {
public Identity doFind(IdentityId identityId){
    if (Logger.isDebugEnabled()) {
        Logger.debug(String.format("finding by Id = %s", identityId.userId()));

    }

    User localUser = User.find.byId(identityId.userId());
    Logger.debug(String.format("localUser = " + localUser));
    if(localUser == null) return null;
    SocialUser socialUser = new SocialUser(new IdentityId(localUser.id, localUser.provider),    
        localUser.firstName, 
        localUser.lastName, 
        String.format("%s %s", localUser.firstName, localUser.lastName),
        Option.apply(localUser.email), 
        null, 
        new AuthenticationMethod("userPassword"),
        null, 
        null, 
        Some.apply(new PasswordInfo("bcrypt", localUser.password, null))
    );  
    if (Logger.isDebugEnabled()) {
        Logger.debug(String.format("socialUser = %s", socialUser));
    }
    return socialUser;
}


@Override
public Identity doFindByEmailAndProvider(String email, String providerId) {
    List<User> list = User.find.where().eq("email", email).eq("provider", providerId).findList();
    if(list.size() != 1){
        Logger.debug("found a null in findByEmailAndProvider...");
        return null;
    }
    User localUser = list.get(0);
    SocialUser socialUser = 
            new SocialUser(new IdentityId(localUser.email, localUser.provider),
                    localUser.firstName, 
                    localUser.lastName, 
                    String.format("%s %s", localUser.firstName, localUser.lastName),
                    Option.apply(localUser.email), 
                    null, 
                    new AuthenticationMethod("userPassword"),
                    null, 
                    null, 
                    Some.apply(new PasswordInfo("bcrypt", localUser.password, null))
               );  
    return socialUser;
}

@Override
public Token doFindToken(String token) {
    if (Logger.isDebugEnabled()) {
        Logger.debug("findToken...");
        Logger.debug(String.format("token = %s", token));
    }
    LocalToken localToken = LocalToken.find.byId(token);
    if(localToken == null) return null;
    Token result = new Token();
    result.uuid = localToken.uuid;
    result.creationTime = new DateTime(localToken.createdAt);
    result.email = localToken.email;
    result.expirationTime = new DateTime(localToken.expireAt);
    result.isSignUp = localToken.isSignUp;
    if (Logger.isDebugEnabled()) {
        Logger.debug(String.format("foundToken = %s", result));
    }
    return result;
}

@Override
public Identity doSave(Identity user) {
    if (Logger.isDebugEnabled()) {
        Logger.debug("save...!_!");
        Logger.debug(String.format("user = %s", user));
    }
    User localUser = null;
    localUser = User.find.byId(user.identityId().userId());
    Logger.debug("id = " + user.identityId().userId());
    Logger.debug("provider = " + user.identityId().providerId());
    Logger.debug("firstName = " + user.firstName());
    Logger.debug("lastName = " + user.lastName());
    Logger.debug(user.fullName() + "");
    Logger.debug("email = " + user.email());
    Logger.debug(user.email().getClass() + "");

    if (localUser == null) {
        Logger.debug("adding new...");
        localUser = new User();
        localUser.id = user.identityId().userId();
        localUser.provider = user.identityId().providerId();
        localUser.firstName = user.firstName();
        localUser.lastName = user.lastName();

        //Temporary solution for twitter which does not have email in OAuth answer
        if(!(user.email().toString()).equals("None")){
            localUser.email = user.email().get();
        }
        if(!(user.passwordInfo() + "").equals("None")){
            localUser.password = user.passwordInfo().get().password();
        }
        localUser.save();
    } else {
        Logger.debug("existing one...");
        localUser.id = user.identityId().userId();
        localUser.provider = user.identityId().providerId();
        localUser.firstName = user.firstName();
        localUser.lastName = user.lastName();

        //Temporary solution for twitter which does not have email in OAuth answer
        if(!(user.email().toString()).equals("None")){
            localUser.email = user.email().get();
        }
        if(!(user.passwordInfo() + "").equals("None")){
            localUser.password = user.passwordInfo().get().password();
        }
        localUser.update();
    }
    return user;
}

@Override
public void doSave(Token token) {
    LocalToken localToken = new LocalToken();
    localToken.uuid = token.uuid;
    localToken.email = token.email;
    try {
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        localToken.createdAt = df.parse(token.creationTime.toString("yyyy-MM-dd HH:mm:ss"));
        localToken.expireAt = df.parse(token.expirationTime.toString("yyyy-MM-dd HH:mm:ss"));
    } catch (ParseException e) {
        Logger.error("UserService.doSave(): ", e);
    }
    localToken.isSignUp = token.isSignUp;
    localToken.save();
}

}

根据我的理解,我应该在某种程度上设置会话,以便用户通过在fakerequest上使用.withsession方法登录,也可以在服务器端设置一些值。

尝试使用securesocial和play在网上搜索示例,但根本没有找到任何测试。

如何登录我的用户以便我可以预先测试?

祝你好运 拉瓦

1 个答案:

答案 0 :(得分:2)

感谢David Weinbergs评论我能够在一些跟踪和错误之后解决这个问题。 (:

我从这个回复中开始了我的LocalUser实现: https://stackoverflow.com/a/18589402/1724097

这就是我解决它的方法:

要进行单元测试,我使用test-data.yml文件在数据库中创建了一个本地用户:

- !!models.LocalUser
    id: 1234567890
    username: Username
    provider: userpass
    firstName: firstName
    lastName: lastName
    email: user@example.com
    #hash for "password"
    password: $2a$10$.VE.rwJFMblRv2HIqhZM5.CiqzYOhhJyLYrKpMmwXar6Vp58U7flW 

然后我创建了一个测试utils类来创建我的fakeCookie。

import models.LocalUser;
import play.Logger;
import securesocial.core.Authenticator;
import securesocial.core.IdentityId;
import securesocial.core.SocialUser;
import securesocial.core.PasswordInfo;
import scala.Some;
import securesocial.core.AuthenticationMethod;
import scala.Option;
import scala.util.Right;
import scala.util.Either;
import play.mvc.Http.Cookie;

public class Utils {


    public static Cookie fakeCookie(String user){

        LocalUser localUser = LocalUser.findByEmail(user);
        Logger.debug("Username: " + localUser.username +" - ID: " + localUser.id);

        SocialUser socialUser = new SocialUser(new IdentityId(localUser.id, localUser.provider),    
            localUser.firstName, 
            localUser.lastName, 
            String.format("%s %s", localUser.firstName, localUser.lastName),
            Option.apply(localUser.email), 
            null, 
            new AuthenticationMethod("userPassword"),
            null, 
            null, 
            Some.apply(new PasswordInfo("bcrypt", localUser.password, null))
        );  

        Either either = Authenticator.create(socialUser);
        Authenticator auth = (Authenticator) either.right().get();
        play.api.mvc.Cookie scalaCookie = auth.toCookie();


        //debug loggig
        Logger.debug("Cookie data:");
        Logger.debug("Name: " + "Value: " + auth.cookieName() + " | Class: " + auth.cookieName().getClass() + " | Should be type: " + "java.lang.String");
        Logger.debug("Value: " + "Value: " + scalaCookie.value() + " | Class: " + scalaCookie.value().getClass() + " | Should be type: " + "java.lang.String");
        Logger.debug("MaxAge: " + "Value: " + scalaCookie.maxAge() + " | Class: " + scalaCookie.maxAge().getClass() + " | Should be type: " + "int");
        Logger.debug("Path: " + "Value: " + scalaCookie.path() + " | Class: " + scalaCookie.path().getClass() + " | Should be type: " + "java.lang.String");
        Logger.debug("Domain: " + "Value: " + scalaCookie.domain() + " | Class: " + auth.cookieDomain().getClass() + " | Should be type: " + "java.lang.String");
        Logger.debug("Secure: " + "Value: " + auth.cookieSecure() + " | Class: " + "Boolean" + " | Should be type: " + "boolean");
        Logger.debug("HttpOnly: " + "Value: " + auth.cookieHttpOnly() + " | Class: " + "Boolean" + " | Should be type: " + "boolean");

        // secureSocial doesnt seem to set a maxAge or Domain so i set them myself.
        Cookie fakeCookie = new Cookie(auth.cookieName(), scalaCookie.value(), 120, scalaCookie.path(), "None", auth.cookieSecure(), auth.cookieHttpOnly());
        return fakeCookie;
    }
}

然后我只是在fakeRequest中使用我的cookie,所以我登录了:

Cookie cookie = Utils.fakeCookie("user@example.com");

Result result = callAction(
        controllers.routes.ref.yourSampleClass.yourSecuredFucntion(),
        fakeRequest().withFormUrlEncodedBody(
                ImmutableMap.of("Value", "Some input value")).withCookies(cookie));

// Should return redirect status if successful
assertThat(status(result)).isEqualTo(SEE_OTHER);
assertThat(redirectLocation(result)).isEqualTo("/yourWantedResult");

希望这有助于其他人!