Thibaut M.
Thibaut M.

Reputation: 299

How to mock an Authenticator in play framework with guice injections?

I have a play application with authenticated routes. I implemented an Authenticator, storing users into elasticsearch. My securized methods in my controllers are annotated with the @Security.Authenticated annotation. For my unit tests with mockito, I would like to mock this class but I don't know how to do this.

I am using DI with Guice. So I tried this approach:

  1. Develop an AuthenticatorWrapper as following:

    public class AuthenticatorWrapper extends Security.Authenticator {
    
        private Authenticator authenticator;
    
        @Override
        public String getUsername(Http.Context ctx) {
            return authenticator.getUsername(ctx);
        }
    
        @Override
        public Result onUnauthorized(Http.Context ctx) {
            return authenticator.onUnauthorized(ctx);
        }
    
        @Inject
        public void setAuthenticator(Authenticator authenticator) {
            this.authenticator = authenticator;
        }
    }
    

    This class has an Authenticator as parameter, which is supposed to be injected by Guice when the app starts.

  2. I developed a guice module defining a binding for class Authenticator.class to MyCustomAuthenticator.class

  3. My securized route are annotated with @Security.Authenticated(AuthenticatorWrapper.class)

In my test I can easily provide a mock of class MyCustomAuthenticator my creating the mock, define test scope guice module, and defining a binding from Authenticator.class to my mock.

I thought this should work but this is not the case. Both at normal runtime or from my tests, the binding seems not working. I have nullPointerException from the wrapper when: the Authenticator parameter is not injected by Guice.

So my questions are:

Thanks :)

Upvotes: 3

Views: 870

Answers (1)

Thibaut M.
Thibaut M.

Reputation: 299

A found a workaround. I just used an access method provided by Play framework 2.4 since it fully integrates Guice. Here is my Authentication Wrapper class:

public class AuthenticatorWrapper extends Security.Authenticator {

    private final Security.Authenticator authenticator;

    public AuthenticatorWrapper() {
        authenticator = Play.application().injector().instanceOf(Security.Authenticator.class);
    }

    @Override
    public String getUsername(Http.Context ctx) {
        return authenticator.getUsername(ctx);
    }

    @Override
    public Result onUnauthorized(Http.Context ctx) {
        return authenticator.onUnauthorized(ctx);
    }
}

I just use the Play.application().injector() accessor to get a Security.Authenticator instance provided by Guice. So in my application.conf, I just configure a Guice Module which binds Security.Authenticator to the wanted implementation.

Upvotes: 0

Related Questions