Package org.junithelper.core.generator.impl

Source Code of org.junithelper.core.generator.impl.DefaultTestMethodGenerator

/*
* Copyright 2009-2010 junithelper.org.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific language
* governing permissions and limitations under the License.
*/
package org.junithelper.core.generator.impl;

import java.util.ArrayList;
import java.util.List;
import org.junithelper.core.config.Configuration;
import org.junithelper.core.config.JUnitVersion;
import org.junithelper.core.config.MessageValue;
import org.junithelper.core.config.MockObjectFramework;
import org.junithelper.core.config.TestingPatternExplicitComment;
import org.junithelper.core.constant.RegExp;
import org.junithelper.core.constant.StringValue;
import org.junithelper.core.generator.ConstructorGenerator;
import org.junithelper.core.generator.TestMethodGenerator;
import org.junithelper.core.meta.ArgTypeMeta;
import org.junithelper.core.meta.ClassMeta;
import org.junithelper.core.meta.ExceptionMeta;
import org.junithelper.core.meta.MethodMeta;
import org.junithelper.core.meta.TestMethodMeta;
import org.junithelper.core.parser.detect.AvailableTypeDetector;
import org.junithelper.core.util.PrimitiveTypeUtil;

public class DefaultTestMethodGenerator implements TestMethodGenerator {

  private Configuration config;
  private ClassMeta targetClassMeta;
  private MessageValue messageValue = new MessageValue();
  private ConstructorGenerator constructorGenerator = new DefaultConstructorGenerator();

  public DefaultTestMethodGenerator(Configuration config) {
    this.config = config;
  }

  @Override
  public void initialize(ClassMeta targetClassMeta) {
    this.targetClassMeta = targetClassMeta;
    messageValue.initialize(config.language);
  }

  @Override
  public TestMethodMeta getTestMethodMeta(MethodMeta targetMethodMeta) {
    return getTestMethodMeta(targetMethodMeta, null);
  }

  @Override
  public TestMethodMeta getTestMethodMeta(MethodMeta targetMethodMeta, ExceptionMeta exception) {
    if (targetClassMeta == null) {
      throw new IllegalStateException("Not initialized");
    }
    TestMethodMeta testMethodMeta = new TestMethodMeta();
    testMethodMeta.classMeta = targetClassMeta;
    testMethodMeta.methodMeta = targetMethodMeta;
    testMethodMeta.testingTargetException = exception;
    return testMethodMeta;
  }

  @Override
  public String getTestMethodNamePrefix(TestMethodMeta testMethodMeta) {
    return getTestMethodNamePrefix(testMethodMeta, null);
  }

  @Override
  public String getTestMethodNamePrefix(TestMethodMeta testMethodMeta, ExceptionMeta exception) {
    MethodMeta targetMethodMeta = testMethodMeta.methodMeta;
    // testing instantiation
    if (targetMethodMeta == null) {
      if (testMethodMeta.isTypeTest) {
        return "type";
      } else if (testMethodMeta.isInstantiationTest) {
        return "instantiation";
      }
    }
    StringBuilder buf = new StringBuilder();
    buf.append(targetMethodMeta.name);
    if (config.testMethodName.isArgsRequired) {
      buf.append(config.testMethodName.basicDelimiter);
      buf.append(config.testMethodName.argsAreaPrefix);
      if (targetMethodMeta.argTypes.size() == 0) {
        buf.append(config.testMethodName.argsAreaDelimiter);
      } else {
        for (ArgTypeMeta argType : targetMethodMeta.argTypes) {
          buf.append(config.testMethodName.argsAreaDelimiter);
          buf.append(argType.nameInMethodName);
        }
      }
    }
    if (config.testMethodName.isReturnRequired) {
      buf.append(config.testMethodName.basicDelimiter);
      buf.append(config.testMethodName.returnAreaPrefix);
      buf.append(config.testMethodName.returnAreaDelimiter);
      if (targetMethodMeta.returnType.nameInMethodName == null) {
        buf.append("void");
      } else {
        buf.append(targetMethodMeta.returnType.nameInMethodName);
      }
    }
    if (exception != null) {
      buf.append(config.testMethodName.basicDelimiter);
      buf.append(config.testMethodName.exceptionAreaPrefix);
      buf.append(config.testMethodName.exceptionAreaDelimiter);
      buf.append(exception.nameInMethodName);
    }
    return buf.toString();
  }

  @Override
  public String getTestMethodSourceCode(TestMethodMeta testMethodMeta) {

    StringBuilder buf = new StringBuilder();

    // JMockit
    if (config.mockObjectFramework == MockObjectFramework.JMockit) {
      List<String> mockedFieldsForJMockit = getMockedFieldsForJMockit(testMethodMeta);
      for (String mocked : mockedFieldsForJMockit) {
        appendTabs(buf, 1);
        buf.append("@Mocked ");
        appendCRLF(buf);
        appendTabs(buf, 1);
        buf.append(mocked);
        buf.append(StringValue.Semicolon);
        appendCRLF(buf);
      }
      if (mockedFieldsForJMockit.size() > 0) {
        appendCRLF(buf);
      }
    }

    // test method signature
    if (config.junitVersion == JUnitVersion.version3) {
      appendTabs(buf, 1);
      buf.append("public void ");
      buf.append(StringValue.JUnit.TestMethodNamePrefixForJUnitVersion3);
      buf.append(config.testMethodName.basicDelimiter);
    } else {
      appendTabs(buf, 1);
      buf.append("@Test");
      appendCRLF(buf);
      appendTabs(buf, 1);
      buf.append("public void ");
    }
    buf.append(getTestMethodNamePrefix(testMethodMeta, testMethodMeta.testingTargetException));
    boolean isThrowableRequired = false;
    if (testMethodMeta.methodMeta != null && testMethodMeta.methodMeta.throwsExceptions != null) {
      for (ExceptionMeta ex : testMethodMeta.methodMeta.throwsExceptions) {
        if (ex.name.equals("Throwable")) {
          isThrowableRequired = true;
          break;
        }
      }
    }
    buf.append("() throws ");
    buf.append(isThrowableRequired ? "Throwable" : "Exception");
    buf.append(" {");
    appendCRLF(buf);

    // auto generated todo message
    appendTabs(buf, 2);
    buf.append("// ");
    buf.append(messageValue.getAutoGeneratedTODOMessage());
    appendCRLF(buf);

    if (testMethodMeta.isTypeTest) {
      // testing type safe
      appendTabs(buf, 2);
      if (config.junitVersion == JUnitVersion.version3) {
        buf.append("assertNotNull(");
        buf.append(testMethodMeta.classMeta.name);
        buf.append(".class);");
      } else {
        buf.append("assertThat(");
        buf.append(testMethodMeta.classMeta.name);
        buf.append(".class, notNullValue());");
      }
      appendCRLF(buf);

    } else if (testMethodMeta.isInstantiationTest) {
      // testing instantiation
      String instantiation = constructorGenerator.getFirstInstantiationSourceCode(testMethodMeta.classMeta);
      buf.append(instantiation);
      appendTabs(buf, 2);
      if (config.junitVersion == JUnitVersion.version3) {
        buf.append("assertNotNull(target);");
      } else {
        buf.append("assertThat(target, notNullValue());");
      }
      appendCRLF(buf);

    } else if (config.isTemplateImplementationRequired) {

      // Arrange or Given
      appendTestingPatternExplicitComment(buf, "Arrange", 2);

      // prepare for Mock object framework
      if (config.mockObjectFramework == MockObjectFramework.JMock2) {
        appendTabs(buf, 2);
        buf.append("Mockery context = new Mockery(){{");
        appendCRLF(buf);
        appendTabs(buf, 3);
        buf.append("setImposteriser(ClassImposteriser.INSTANCE);");
        appendCRLF(buf);
        appendTabs(buf, 2);
        buf.append("}};");
        appendCRLF(buf);
      }
      if (config.mockObjectFramework == MockObjectFramework.EasyMock) {
        appendTabs(buf, 2);
        buf.append("IMocksControl mocks = EasyMock.createControl();");
        appendCRLF(buf);
      }
      // instantiation if testing an instance method
      if (!testMethodMeta.methodMeta.isStatic) {
        String instantiation = constructorGenerator.getFirstInstantiationSourceCode(testMethodMeta.classMeta);
        buf.append(instantiation);
      }
      // Mockito BDD
      appendBDDMockitoComment(buf, "given", 2);

      if (testMethodMeta.testingTargetException == null) {
        // --------------------------------
        // Normal pattern testing
        // --------------------------------
        // prepare args
        appendPreparingArgs(buf, testMethodMeta);
        // mock/stub checking
        appendMockChecking(buf, 2);
        // Act or When
        appendTestingPatternExplicitComment(buf, "Act", 2);
        // Mockito BDD
        appendBDDMockitoComment(buf, "when", 2);
        // return value
        if (testMethodMeta.methodMeta.returnType != null && testMethodMeta.methodMeta.returnType.name != null) {
          appendTabs(buf, 2);
          buf.append(testMethodMeta.methodMeta.returnType.name);
          buf.append(" actual = ");
        } else {
          appendTabs(buf, 2);
        }
        // execute target method
        appendExecutingTargetMethod(buf, testMethodMeta);
        // Assert or Then
        appendTestingPatternExplicitComment(buf, "Assert", 2);
        // Mockito BDD
        appendBDDMockitoComment(buf, "then", 2);
        appendMockVerifying(buf, 2);
        // check return value
        if (testMethodMeta.methodMeta.returnType != null && testMethodMeta.methodMeta.returnType.name != null) {
          appendTabs(buf, 2);
          buf.append(testMethodMeta.methodMeta.returnType.name);
          buf.append(" expected = ");
          if (PrimitiveTypeUtil.isPrimitive(testMethodMeta.methodMeta.returnType.name)) {
            buf.append(PrimitiveTypeUtil.getTypeDefaultValue(testMethodMeta.methodMeta.returnType.name));
          } else {
            buf.append("null");
          }
          buf.append(StringValue.Semicolon);
          appendCRLF(buf);
          // assertion
          appendTabs(buf, 2);
          if (config.junitVersion == JUnitVersion.version3) {
            buf.append("assertEquals(expected, actual)");
          } else {
            buf.append("assertThat(actual, is(equalTo(expected)))");
          }
          buf.append(StringValue.Semicolon);
          appendCRLF(buf);
        }
      } else {
        // --------------------------------
        // Exception pattern testing
        // --------------------------------
        // prepare args
        appendPreparingArgs(buf, testMethodMeta);
        // mock/stub checking
        appendMockChecking(buf, 2);
        // try
        appendTabs(buf, 2);
        buf.append("try {");
        appendCRLF(buf);
        // Assert or Then
        appendTestingPatternExplicitComment(buf, "Assert", 3);
        // Mockito BDD
        appendBDDMockitoComment(buf, "when", 3);
        // execute target method
        appendTabs(buf, 3);
        appendExecutingTargetMethod(buf, testMethodMeta);
        // fail when no exception
        appendTabs(buf, 3);
        buf.append("fail(\"Expected exception was not thrown!\")");
        buf.append(StringValue.Semicolon);
        appendCRLF(buf);
        // catch
        appendTabs(buf, 2);
        buf.append("} catch (");
        buf.append(testMethodMeta.testingTargetException.name);
        buf.append(" e) {");
        appendCRLF(buf);
        // Mockito BDD
        appendBDDMockitoComment(buf, "then", 3);
        appendTabs(buf, 2);
        buf.append("}");
        appendCRLF(buf);
      }
    }
    appendTabs(buf, 1);
    buf.append("}");
    appendCRLF(buf);

    return buf.toString();
  }

  void appendCRLF(StringBuilder buf) {
    buf.append(StringValue.CarriageReturn);
    buf.append(StringValue.LineFeed);
  }

  void appendTabs(StringBuilder buf, int times) {
    for (int i = 0; i < times; i++) {
      buf.append(StringValue.Tab);
    }
  }

  void appendPreparingArgs(StringBuilder buf, TestMethodMeta testMethodMeta) {
    // prepare args
    int argsLen = testMethodMeta.methodMeta.argTypes.size();
    if (argsLen > 0) {
      for (int i = 0; i < argsLen; i++) {
        appendTabs(buf, 2);
        if (config.mockObjectFramework == MockObjectFramework.JMock2) {
          buf.append("final ");
        }
        ArgTypeMeta argTypeMeta = testMethodMeta.methodMeta.argTypes.get(i);
        String typeName = argTypeMeta.name;
        String argName = testMethodMeta.methodMeta.argNames.get(i);
        buf.append(typeName);
        buf.append(" ");
        buf.append(argName);
        buf.append(" = ");
        buf.append(getArgValue(testMethodMeta, argTypeMeta, argName));
        buf.append(StringValue.Semicolon);
        appendCRLF(buf);
      }
    }
  }

  void appendMockChecking(StringBuilder buf, int depth) {
    if (config.mockObjectFramework == MockObjectFramework.EasyMock) {
      appendTabs(buf, depth);
      buf.append("// ");
      buf.append(messageValue.getExempliGratia());
      buf.append(" : ");
      buf.append("EasyMock.expect(mocked.called()).andReturn(1);");
      appendCRLF(buf);
      appendTabs(buf, depth);
      buf.append("mocks.replay();");
      appendCRLF(buf);
    } else if (config.mockObjectFramework == MockObjectFramework.JMock2) {
      appendTabs(buf, depth);
      buf.append("context.checking(new Expectations(){{");
      appendCRLF(buf);
      appendTabs(buf, depth + 1);
      buf.append("// ");
      buf.append(messageValue.getExempliGratia());
      buf.append(" : ");
      buf.append("allowing(mocked).called(); will(returnValue(1));");
      appendCRLF(buf);
      appendTabs(buf, depth);
      buf.append("}});");
      appendCRLF(buf);
    } else if (config.mockObjectFramework == MockObjectFramework.JMockit) {
      appendTabs(buf, depth);
      buf.append("new Expectations(){{");
      appendCRLF(buf);
      appendTabs(buf, depth + 1);
      buf.append("// ");
      buf.append(messageValue.getExempliGratia());
      buf.append(" : ");
      buf.append("mocked.get(anyString); returns(200);");
      appendCRLF(buf);
      appendTabs(buf, depth);
      buf.append("}};");
      appendCRLF(buf);
    } else if (config.mockObjectFramework == MockObjectFramework.Mockito) {
      appendTabs(buf, depth);
      buf.append("// ");
      buf.append(messageValue.getExempliGratia());
      buf.append(" : ");
      buf.append("given(mocked.called()).willReturn(1);");
      appendCRLF(buf);
    }
  }

  void appendMockVerifying(StringBuilder buf, int depth) {
    // verfiy
    if (config.mockObjectFramework == MockObjectFramework.EasyMock) {
      appendTabs(buf, depth);
      buf.append("mocks.verify();");
      appendCRLF(buf);
    }
    if (config.mockObjectFramework == MockObjectFramework.Mockito) {
      appendTabs(buf, depth);
      buf.append("// ");
      buf.append(messageValue.getExempliGratia());
      buf.append(" : ");
      buf.append("verify(mocked).called();");
      appendCRLF(buf);
    }
  }

  void appendExecutingTargetMethod(StringBuilder buf, TestMethodMeta testMethodMeta) {
    String actor = (testMethodMeta.methodMeta.isStatic) ? testMethodMeta.classMeta.name : "target";
    buf.append(actor);
    buf.append(".");
    buf.append(testMethodMeta.methodMeta.name);
    buf.append("(");
    int argsLen = testMethodMeta.methodMeta.argTypes.size();
    if (argsLen > 0) {
      buf.append(testMethodMeta.methodMeta.argNames.get(0));
    }
    if (argsLen > 1) {
      for (int i = 1; i < argsLen; i++) {
        buf.append(StringValue.Comma);
        buf.append(StringValue.Space);
        buf.append(testMethodMeta.methodMeta.argNames.get(i));
      }
    }
    buf.append(")");
    buf.append(StringValue.Semicolon);
    appendCRLF(buf);
  }

  void appendBDDMockitoComment(StringBuilder buf, String value, int depth) {
    if (config.mockObjectFramework == MockObjectFramework.Mockito) {
      appendTabs(buf, depth);
      buf.append("// ");
      buf.append(value);
      appendCRLF(buf);
    }
  }

  void appendTestingPatternExplicitComment(StringBuilder buf, String value, int depth) {
    if (config.testingPatternExplicitComment != TestingPatternExplicitComment.None
        && config.mockObjectFramework != MockObjectFramework.Mockito) {
      if (config.testingPatternExplicitComment == TestingPatternExplicitComment.GivenWhenThen) {
        if (value.equals("Arrange")) {
          value = "Given";
        } else if (value.equals("Act")) {
          value = "When";
        } else if (value.equals("Assert")) {
          value = "Then";
        }
      }
      appendTabs(buf, depth);
      buf.append("// ");
      buf.append(value);
      appendCRLF(buf);
    }
  }

  List<String> getMockedFieldsForJMockit(TestMethodMeta testMethodMeta) {
    List<String> dest = new ArrayList<String>();
    if (testMethodMeta.methodMeta != null) {
      int len = testMethodMeta.methodMeta.argTypes.size();
      for (int i = 0; i < len; i++) {
        String typeName = testMethodMeta.methodMeta.argTypes.get(i).name;
        if (PrimitiveTypeUtil.isPrimitive(typeName)) {
          continue;
        }
        if (!new AvailableTypeDetector(targetClassMeta).isJMockitMockableType(typeName)) {
          continue;
        }
        ArgTypeMeta argTypeMeta = testMethodMeta.methodMeta.argTypes.get(i);
        String argName = testMethodMeta.methodMeta.argNames.get(i);
        String value = getArgValue(testMethodMeta, argTypeMeta, argName);
        if (value.equals("this."
            + getTestMethodNamePrefix(testMethodMeta, testMethodMeta.testingTargetException) + "_"
            + argName)) {
          dest.add(argTypeMeta.name + " " + value.replace("this.", ""));
        }
      }
    }
    return dest;
  }

  String getArgValue(TestMethodMeta testMethodMeta, ArgTypeMeta argTypeMeta, String argName) {
    AvailableTypeDetector availableTypeDetector = new AvailableTypeDetector(targetClassMeta);
    if (availableTypeDetector.isJavaLangPackageType(argTypeMeta.name)) {
      return "null";
    } else if (PrimitiveTypeUtil.isPrimitive(argTypeMeta.name)) {
      return PrimitiveTypeUtil.getTypeDefaultValue(argTypeMeta.name);
    } else if (argTypeMeta.name.matches(".+?\\[\\]$")) {
      return "new " + argTypeMeta.name + " {}";
    } else if (argTypeMeta.name.matches("List(<[^>]+>)?")
        && availableTypeDetector.isAvailableType("java.util.List", config)) {
      targetClassMeta.importedList.add("java.util.ArrayList");
      String genericsString = argTypeMeta.getGenericsAsString();
      if (genericsString.equals("<?>")) {
        genericsString = "";
      }
      return "new ArrayList" + genericsString + "()";
    } else if (argTypeMeta.name.matches("Map(<[^>]+>)?")
        && availableTypeDetector.isAvailableType("java.util.Map", config)) {
      targetClassMeta.importedList.add("java.util.HashMap");
      String genericsString = argTypeMeta.getGenericsAsString();
      if (genericsString.matches("<.*\\?.*>")) {
        genericsString = "";
      }
      return "new HashMap" + genericsString + "()";
    } else if (config.mockObjectFramework == MockObjectFramework.EasyMock) {
      return "mocks.createMock(" + argTypeMeta.name.replaceAll(RegExp.Generics, StringValue.Empty) + ".class)";
    } else if (config.mockObjectFramework == MockObjectFramework.JMock2) {
      return "context.mock(" + argTypeMeta.name.replaceAll(RegExp.Generics, StringValue.Empty) + ".class)";
    } else if (config.mockObjectFramework == MockObjectFramework.JMockit) {
      if (new AvailableTypeDetector(targetClassMeta).isJMockitMockableType(argTypeMeta.name)) {
        return "this." + getTestMethodNamePrefix(testMethodMeta, testMethodMeta.testingTargetException) + "_"
            + argName;
      } else {
        return "null";
      }
    } else if (config.mockObjectFramework == MockObjectFramework.Mockito) {
      return "mock(" + argTypeMeta.name.replaceAll(RegExp.Generics, StringValue.Empty) + ".class)";
    } else {
      return "null";
    }
  }

}
TOP

Related Classes of org.junithelper.core.generator.impl.DefaultTestMethodGenerator

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.