mardi 27 février 2018

Spring MockMvc testing with Java based config

I am using MockMvc for testing web application, but have faced with some issues.

When I tried to run simple request without getting any bean from appContext it works perfect, but for example get bean of password encoder from appContext - returns null. So, how can I load my beans to application context?

LoginTest.class

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
public class LoginTest {

private static String user = "bla@bla.com";
private static String pass = "bla";
private static String source = "API";

private MockMvc mockMvc;

@Before
public void setup() {
    mockMvc = MockMvcBuilders.standaloneSetup(new AuthController()).build();
}

@Test
public void requestScope() throws CustomException {
    try {
        mockMvc.perform(post("/getToken").contentType(MediaType.APPLICATION_FORM_URLENCODED)
                .content(EntityUtils.toString(new UrlEncodedFormEntity(Arrays.<BasicNameValuePair>asList(
                        new BasicNameValuePair("email", user),
                        new BasicNameValuePair("password", pass),
                        new BasicNameValuePair("source", source),
                        new BasicNameValuePair("redirect", "/")
                ))))).andExpect(status().isOk());
    } catch (Exception e) {
        System.out.println(e.getMessage());
        e.printStackTrace();
    }
}

}

My console output:

    org.springframework.web.util.NestedServletException: Handler processing failed; nested exception is java.lang.ExceptionInInitializerError
    at org.springframework.web.servlet.DispatcherServlet.triggerAfterCompletionWithError(DispatcherServlet.java:1303)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:977)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:893)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:967)
    at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:869)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:707)
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:843)
    at org.springframework.test.web.servlet.TestDispatcherServlet.service(TestDispatcherServlet.java:65)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
    at org.springframework.mock.web.MockFilterChain$ServletFilterProxy.doFilter(MockFilterChain.java:160)
    at org.springframework.mock.web.MockFilterChain.doFilter(MockFilterChain.java:127)
    at org.springframework.test.web.servlet.MockMvc.perform(MockMvc.java:155)
    at LoginTest.requestScope(LoginTest.java:70)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
    at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)
    at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
    at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:252)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
    at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:538)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:760)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:460)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:206)
Caused by: java.lang.ExceptionInInitializerError
    at main.java.controller.AuthController.getToken(AuthController.java:40)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:220)
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:134)
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:110)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:776)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:705)
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:959)
    ... 41 more
Caused by: java.lang.NullPointerException
    at main.java.service.context.ApplicationContextService.getBean(ApplicationContextService.java:30)
    at main.java.conf.TokenAuthenticationService.<clinit>(TokenAuthenticationService.java:31)
    ... 53 more

AuthController.class

@Controller
@RequestMapping("/")
public class AuthController {

    private static JWTConfig config = ConfigService.get().getJWTConfig();
    private static Gson gson = new GsonBuilder().disableHtmlEscaping().create();

    // Get a new JWT token for a given email/password
    @RequestMapping(value = "/getToken", method = RequestMethod.POST)
    @ResponseBody
    public String getToken(
            @RequestParam(value = "email") String user,
            @RequestParam String password,
            @RequestParam String source,
            HttpServletRequest request,
            HttpServletResponse response) {
        try {
            String jwtAuthToken = TokenAuthenticationService.getAuthToken(user, password, source);
            if (source.equals("web")) {
                response.addCookie(new Cookie(config.cookiesString, jwtAuthToken));
            } else {
                response.addHeader(config.headerString, config.tokenPrefix + " " + jwtAuthToken);
            }
            JsonObject jwtData = new JsonObject();
            jwtData.addProperty("jwt", jwtAuthToken);
            return gson.toJson(jwtData);
        } catch (Exception e) {
            return Logger.getExceptionJsonResponse("[AuthController] Exception in getToken method.", e, response);
        }
    }
}

TokenAuthenticationService

public class TokenAuthenticationService {

    private static JWTConfig config = ConfigService.get().getJWTConfig();
//    private static PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
    private static PasswordEncoder passwordEncoder = ApplicationContextService.getBean(PasswordEncoder.class);

    public static String getAuthToken(String username, String password, String source) throws Jp3Exception {
        User user = new UserServiceImpl().getUserByEmail(username, true);
        if (user == null) {
            String message = "Wrong username.";
            JP3Logger.info("[TokenAuthenticationService] Cannot create auth token for user `" + username + "`.");
            throw new Jp3Exception(message);
        }
        if (!passwordEncoder.matches(password, user.getPassword())) {
            String message = "Wrong user password.";
            JP3Logger.info("[TokenAuthenticationService] Cannot create auth token for user `" + username + "`.");
            throw new Jp3Exception(message);
        }
        UUID jwtId = UUID.randomUUID();
        String sub = getSubject(source);
        // Expiration date equals null if expiration time would be null
        Date exp = config.expirationTime != null ? new Date(System.currentTimeMillis() + config.expirationTime) : null;
        String permissions = new UserManagementServiceImpl().getUserPermissions(user.getId(), false).toString();
        permissions = permissions.replace("{", "[").replace("}", "]").replaceAll("\"", "");
        String jwt = Jwts.builder().setIssuer(config.issuer).setIssuedAt(new Date(System.currentTimeMillis())).setExpiration(exp)
                .claim("jwtid", jwtId).setSubject(sub)
                .claim("_id", user.getId())
                .claim("email", user.getUsername())
                .claim("permissions", permissions)
                .signWith(SignatureAlgorithm.HS256, config.secret).compact();

        //Add user to Spring Security Context Holder
        //UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken(user, password, Collections.emptyList());
        //Authentication auth = authenticationManager.authenticate(authToken);
        //SecurityContextHolder.getContext().setAuthentication(auth);

        return jwt;
    }

ApplicationContextService

public class ApplicationContextService implements ApplicationContextAware {

    private static ApplicationContext appContext;
    private static long lastFailedDbConnectTime = 0;
    private static long checkConnectionTimeframe = 1000 * 30;// 1 min frame before the next check

    public static ApplicationContext getApplicationContext() {
        return appContext;
    }

    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        appContext = applicationContext;
    }

    public static void setApplicationContextStatic(ApplicationContext ac) {
        appContext = ac;
    }

    public static <T> T getBean(Class<T> clazz) {
        return appContext.getBean(clazz);
    }

    @SuppressWarnings("unchecked")
    public static <T> T getBean(String beanId) {
        return (T) appContext.getBean(beanId);
    }

   public static boolean isMainDataBaseAvailable() {
        try {
            if ((System.currentTimeMillis() - lastFailedDbConnectTime) < checkConnectionTimeframe) {
                return false;
            }
            HikariDataSource hikariCPMain = (HikariDataSource) appContext.getBean("HikariCPMain");
            long timeout = hikariCPMain.getConnectionTimeout();
            hikariCPMain.setConnectionTimeout(9500);
            hikariCPMain.getConnection().close();
            hikariCPMain.setConnectionTimeout(timeout);//restore default DB timeout
            return true;
        } catch (Exception e) {
            JP3Logger.error("[ApplicationContextService] Exception in isMainDataBaseAvailable method. Cannot connect to main database.", e, false);
            //HikariDataSource hikariCPAlternative = (HikariDataSource) appContext.getBean("HikariCPAlternative");
            lastFailedDbConnectTime = System.currentTimeMillis();
            return false;
        }
    }

    public static HikariDataSource getHikariDataSource() {
        return (HikariDataSource) appContext.getBean(ApplicationContextService.isMainDataBaseAvailable() ? "HikariCPMain" : "HikariCPAlternative");
    }

Seems that application context doesn`t have proper beans, or even equal null. Please help me, I am stuck with it.

Aucun commentaire:

Enregistrer un commentaire