Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
   *
   *              C E D A R
   *          S O L U T I O N S       "Software done right."
   *           S O F T W A R E
   *
   * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
   *
   * Copyright (c) 2013-2014 Kenneth J. Pronovici.
  * All rights reserved.
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the Apache License, Version 2.0.
  * See LICENSE for more information about the licensing terms.
  *
  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  *
  * Author   : Kenneth J. Pronovici <pronovic@ieee.org>
  * Language : Java 6
  * Project  : Common Java Functionality
  *
  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
 package com.cedarsolutions.junit.gwt.classloader;
 
 import static org.mockito.Mockito.mock;
 
 import java.util.List;
 import java.util.Map;
 
 
Creates mocked versions of objects for stubbed GWT client tests.

This class creates all of its resources as Mockito mocks. There is also some additional logic layered on top to handle certain particular types of interfaces and classes, like Constants or Messages.

This class was derived in part from source code in gwt-test-utils. See README.credits for more information.

This whole thing has sort of a hack-ish feel. There's no simple way to emulate GWT's behavior, and I can basically only make it work by trial- and-error.

Author(s):
Kenneth J. Pronovici <pronovic@ieee.org>
 
 @SuppressWarnings("unchecked")
 public class GwtResourceCreator {

    
Create a mocked resource for a particular class.
 
     public static synchronized <T> T create(Class<?> clazz) {
         if (ConstantsWithLookup.class.isAssignableFrom(clazz)) {
             // ConstantsWithLookup extends Constants, so do this first
             return (T) mock(clazznew ConstantsWithLookupAnswer(clazz));
         } else if (Constants.class.isAssignableFrom(clazz)) {
             return (T) mock(clazznew ConstantsAnswer());
         } else if (Messages.class.isAssignableFrom(clazz)) {
             return (T) mock(clazznew MessagesAnswer());
         } else {
             return (T) mock(clazz);
         }
     }

    
Uses reflection to return proper values for mocks that implement ConstantsWithLookup.
 
     public static class ConstantsWithLookupAnswer implements Answer<Object> {
         private Class<?> clazz;  // there's no other way to get the class that's actually being mocked
 
         public ConstantsWithLookupAnswer(Class<?> clazz) {
             this. = clazz;
         }
 
         @Override
        public Object answer(InvocationOnMock invocationthrows Throwable {
            return getConstantsWithLookupAnswer(invocation);
        }
    }

    
Uses reflection to return proper values for mocks that implement Constants.
    public static class ConstantsAnswer implements Answer<Object> {
        @Override
        public Object answer(InvocationOnMock invocationthrows Throwable {
            return getConstantsAnswer(invocationinvocation.getMethod());
        }
    }

    
Uses reflection to return proper values for mocks that implement Messages.
    public static class MessagesAnswer implements Answer<Object> {
        @Override
        public Object answer(InvocationOnMock invocationthrows Throwable {
            return getMessagesAnswer(invocation);
        }
    }

    
Generate a result for MessagesAnswer.
    private static Object getMessagesAnswer(InvocationOnMock invocationthrows Throwable {
        Object answer = ..answer(invocation);
        for (Annotation annotation : invocation.getMethod().getDeclaredAnnotations()) {
            if (annotation instanceof DefaultMessage) {
                String message = ((DefaultMessageannotation).value();
                return substituteReplaceVariables(messageinvocation.getArguments());
            }
        }
        return answer;
    }

    
Generate a result for ConstantsWithLookupAnswer, which behaves similar to Constants except with possible indirection.
    private static Object getConstantsWithLookupAnswer(Class<?> clazzInvocationOnMock invocationthrows NoSuchMethodExceptionThrowable {
        if ("getBoolean".equals(invocation.getMethod().getName())) {
            return getConstantsAnswer(invocationclazz.getMethod((Stringinvocation.getArguments()[0]));
        } else if ("getDouble".equals(invocation.getMethod().getName())) {
            return getConstantsAnswer(invocationclazz.getMethod((Stringinvocation.getArguments()[0]));
        } else if ("getFloat".equals(invocation.getMethod().getName())) {
            return getConstantsAnswer(invocationclazz.getMethod((Stringinvocation.getArguments()[0]));
        } else if ("getInt".equals(invocation.getMethod().getName())) {
            return getConstantsAnswer(invocationclazz.getMethod((Stringinvocation.getArguments()[0]));
        } else if ("getString".equals(invocation.getMethod().getName())) {
            return getConstantsAnswer(invocationclazz.getMethod((Stringinvocation.getArguments()[0]));
        } else if ("getStringArray".equals(invocation.getMethod().getName())) {
            return getConstantsAnswer(invocationclazz.getMethod((Stringinvocation.getArguments()[0]));
        } else if ("getMap".equals(invocation.getMethod().getName())) {
            return getConstantsAnswer(invocationclazz.getMethod((Stringinvocation.getArguments()[0]));
        } else {
            return getConstantsAnswer(invocationinvocation.getMethod());
        }
    }

    
Generate a result for ConstantsAnswer.
    private static Object getConstantsAnswer(InvocationOnMock invocationMethod methodthrows Throwable {
        Object answer = ..answer(invocation);
        for (Annotation annotation : method.getDeclaredAnnotations()) {
            if (annotation instanceof DefaultBooleanValue) {
                answer = ((DefaultBooleanValueannotation).value();
            } else if (annotation instanceof DefaultDoubleValue) {
                answer = ((DefaultDoubleValueannotation).value();
            } else if (annotation instanceof DefaultFloatValue) {
                answer = ((DefaultFloatValueannotation).value();
            } else if (annotation instanceof DefaultIntValue) {
                answer = ((DefaultIntValueannotation).value();
            } else if (annotation instanceof DefaultStringArrayValue) {
                answer = ((DefaultStringArrayValueannotation).value();
            } else if (annotation instanceof DefaultStringMapValue) {
                answer = parseDefaultStringMapValue(((DefaultStringMapValueannotation).value());
            } else if (annotation instanceof DefaultStringValue) {
                answer = ((DefaultStringValueannotation).value();
            }
        }
        return answer;
    }

    
Parse a value as from DefaultStringMapValue.
    protected static Map<StringStringparseDefaultStringMapValue(String[] values) {
        Map<StringStringmap = new HashMap<StringString>();
        if (values != null && values.length > 0 && values.length % 2 == 0) {
            for (int i = 0; i < values.lengthi += 2) {
                map.put(values[i], values[i + 1]);
            }
        }
        return map;
    }

    
Substitute/replace parameters in a message.

Parameters:
message Message to subsitute/replace in
arguments List of arguments to take parameters from
Throws:
java.lang.IllegalArgumentException The parameter list doesn't match up with the arguments.
    protected static String substituteReplaceVariables(String messageObject[] argumentsthrows IllegalArgumentException {
        // Pre-validate so that we get out quickly
        if (message == null || arguments == null) {
            throw new IllegalArgumentException("Internal error replacing variables: null input");
        }
        // Make a list of all the argument parameters {0}, {1}, etc.
        List<IntegerargumentParameters = new ArrayList<Integer>();
        for (int i = 0; i < arguments.lengthi++) {
            argumentParameters.add(i);
        }
        // Find all of the parameters in the message, like {0}, {1}, etc.
        Pattern pattern = Pattern.compile("(\\{)([0-9]+)(\\})");
        List<IntegermessageParameters = new ArrayList<Integer>();
        Matcher matcher = pattern.matcher(message);
        while (matcher.find()) {
            int messageParameter = Integer.parseInt(matcher.group(2));
            messageParameters.add(messageParameter);
        }
        // Check that every message parameter has a corresponding argument parameter
        for (Integer argumentParameter : argumentParameters) {
            if (!messageParameters.contains(argumentParameter)) {
                throw new IllegalArgumentException("Required argument " + argumentParameter + " not present: " + message);
            }
        }
        // Check that every argument parameter has a corresponding message parameter
        for (Integer messageParameter : messageParameters) {
            if (!argumentParameters.contains(messageParameter)) {
                throw new IllegalArgumentException("Argument " + messageParameter + " beyond range of arguments: " + message);
            }
        }
        // Now that we know the parameters are valid, replace them with real values.
        String result = message;
        if (arguments.length > 0) {
            for (int i = 0; i < arguments.lengthi++) {
                Object argument = arguments[i];
                String value = argument == null ? "null" : String.valueOf(argument);
                String variable = "{" + i + "}";
                result = result.replace(variablevalue);
            }
        }
        // Return the result, which is always non-null by this point
        return result;
    }
New to GrepCode? Check out our FAQ X