org.assertj.assertions.generator.AssertionGeneratorTest.java Source code

Java tutorial

Introduction

Here is the source code for org.assertj.assertions.generator.AssertionGeneratorTest.java

Source

/**
 * 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.
 *
 * Copyright 2012-2015 the original author or authors.
 */
package org.assertj.assertions.generator;

import static com.google.common.collect.Sets.newHashSet;
import static java.lang.reflect.Modifier.isPublic;
import static org.apache.commons.io.FileUtils.readFileToString;
import static org.apache.commons.lang3.StringUtils.replace;
import static org.assertj.assertions.generator.BaseAssertionGenerator.ABSTRACT_ASSERT_CLASS_PREFIX;
import static org.assertj.assertions.generator.BaseAssertionGenerator.ASSERT_CLASS_FILE_SUFFIX;
import static org.assertj.assertions.generator.util.ClassUtil.collectClasses;
import static org.assertj.assertions.generator.util.ClassUtil.getSimpleNameWithOuterClass;
import static org.assertj.assertions.generator.util.ClassUtil.getSimpleNameWithOuterClassNotSeparatedByDots;
import static org.assertj.core.api.Assertions.assertThat;

import java.io.File;
import java.io.IOException;
import java.sql.SQLException;
import java.util.Set;

import org.assertj.assertions.generator.data.ArtWork;
import org.assertj.assertions.generator.data.BooleanPredicates;
import org.assertj.assertions.generator.data.FieldPropertyClash;
import org.assertj.assertions.generator.data.Keywords;
import org.assertj.assertions.generator.data.Movie;
import org.assertj.assertions.generator.data.Primitives;
import org.assertj.assertions.generator.data.Team;
import org.assertj.assertions.generator.data.nba.Player;
import org.assertj.assertions.generator.data.nba.PlayerAgent;
import org.assertj.assertions.generator.description.ClassDescription;
import org.assertj.assertions.generator.description.converter.ClassToClassDescriptionConverter;
import org.junit.Before;
import org.junit.Test;
import org.junit.experimental.theories.Theories;
import org.junit.experimental.theories.Theory;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@RunWith(Theories.class)
public class AssertionGeneratorTest implements NestedClassesTest, BeanWithExceptionsTest {
    private static final String LINE_SEPARATOR = System.getProperty("line.separator");
    private static final String TARGET_DIRECTORY = "target";
    private static final Logger logger = LoggerFactory.getLogger(AssertionGeneratorTest.class);
    private ClassToClassDescriptionConverter converter;
    private AssertionGenerator assertionGenerator;
    private static final Set<Class<?>> allClasses = newHashSet(new Class<?>[] { Movie.class, ArtWork.class });

    @Before
    public void beforeEachTest() throws IOException {
        converter = new ClassToClassDescriptionConverter();
        assertionGenerator = buildAssertionGenerator();
    }

    public AssertionGenerator buildAssertionGenerator() throws IOException {
        BaseAssertionGenerator assertionGenerator = new BaseAssertionGenerator();
        assertionGenerator.setDirectoryWhereAssertionFilesAreGenerated(TARGET_DIRECTORY);
        return assertionGenerator;
    }

    @Test
    public void should_generate_assertion_for_player_class() throws Exception {
        assertionGenerator.generateCustomAssertionFor(converter.convertToClassDescription(Player.class));
        assertGeneratedAssertClass(Player.class, "PlayerAssert.expected.txt");
    }

    @Test
    public void should_generate_assertion_for_interface() throws Exception {
        assertionGenerator.generateCustomAssertionFor(converter.convertToClassDescription(PlayerAgent.class));
        assertGeneratedAssertClass(PlayerAgent.class, "PlayerAgentAssert.expected.txt");
    }

    @Test
    public void should_generate_assertion_for_class_with_public_fields() throws Exception {
        assertionGenerator.generateCustomAssertionFor(converter.convertToClassDescription(Team.class));
        assertGeneratedAssertClass(Team.class, "TeamAssert.expected.txt");
    }

    @Test
    public void should_generate_assertion_for_class_with_properties_that_clash_with_fields() throws Exception {
        assertionGenerator
                .generateCustomAssertionFor(converter.convertToClassDescription(FieldPropertyClash.class));
        assertGeneratedAssertClass(FieldPropertyClash.class, "FieldPropertyClash.expected.txt");
    }

    @Test
    public void should_generate_assertion_for_class_with_properties_that_clash_with_keywords() throws Exception {
        assertionGenerator.generateCustomAssertionFor(converter.convertToClassDescription(Keywords.class));
        assertGeneratedAssertClass(Keywords.class, "Keywords.expected.txt");
    }

    @Test
    public void should_generate_assertion_for_class_with_predicates() throws Exception {
        assertionGenerator.generateCustomAssertionFor(converter.convertToClassDescription(BooleanPredicates.class));
        assertGeneratedAssertClass(BooleanPredicates.class, "BooleanPredicates.expected.txt");
    }

    @Test
    public void should_generate_assertion_for_class_with_primitives() throws Exception {
        assertionGenerator.generateCustomAssertionFor(converter.convertToClassDescription(Primitives.class));
        assertGeneratedAssertClass(Primitives.class, "PrimitivesAssert.expected.txt");
    }

    @Test
    public void should_generate_flat_assertion_for_movie_class() throws Exception {
        abstractFileGeneratedFor(Movie.class).delete();
        assertionGenerator.generateCustomAssertionFor(converter.convertToClassDescription(Movie.class));
        assertGeneratedAssertClass(Movie.class, "MovieAssert.flat.expected.txt");
        assertThat(abstractFileGeneratedFor(Movie.class)).doesNotExist();
    }

    @Test
    public void should_generate_hierarchical_assertion_for_movie_class() throws Exception {
        assertionGenerator.generateHierarchicalCustomAssertionFor(converter.convertToClassDescription(Movie.class),
                allClasses);
        assertGeneratedAssertClass(Movie.class, "MovieAssert.expected.txt");
        assertAbstractGeneratedAssertClass(Movie.class, "AbstractMovieAssert.expected.txt");
    }

    @Test
    public void should_generate_hierarchical_assertion_for_artwork_class() throws Exception {
        assertionGenerator.generateHierarchicalCustomAssertionFor(
                converter.convertToClassDescription(ArtWork.class), allClasses);
        assertGeneratedAssertClass(ArtWork.class, "ArtWorkAssert.expected.txt");
        assertAbstractGeneratedAssertClass(ArtWork.class, "AbstractArtWorkAssert.expected.txt");
    }

    @Theory
    public void should_generate_assertion_for_nested_class(NestedClass nestedClass) throws Exception {
        Class<?> clazz = nestedClass.getNestedClass();
        assertionGenerator.generateCustomAssertionFor(converter.convertToClassDescription(clazz));
        assertThat(fileGeneratedFor(clazz))
                .hasContent(expectedContentFromTemplate(clazz, "NestedClassAssert.template.expected.txt"));
    }

    @Theory
    public void should_generate_hierarchical_assertion_for_nested_class(NestedClass nestedClass) throws Exception {
        Class<?> clazz = nestedClass.getNestedClass();
        assertionGenerator.generateHierarchicalCustomAssertionFor(converter.convertToClassDescription(clazz), null);
        assertThat(fileGeneratedFor(clazz)).hasContent(
                expectedContentFromTemplate(clazz, "NestedClassAssert.hierarchical.template.expected.txt"));
    }

    @Theory
    public void should_generate_assertion_for_property_with_exception(Class<?> beanClass) throws Exception {
        assertionGenerator.generateCustomAssertionFor(converter.convertToClassDescription(beanClass));
        String expectedContent = readFileToString(new File("src/test/resources/BeanWithOneException.expected.txt"));
        if (!BEAN_WITH_ONE_EXCEPTION.equals(beanClass)) {
            expectedContent = expectedContent.replace(BEAN_WITH_ONE_EXCEPTION.getSimpleName(),
                    beanClass.getSimpleName());
            expectedContent = expectedContent.replace(" throws java.io.IOException ",
                    " throws java.io.IOException, java.sql.SQLException ");

            GetterWithException[] getters = { STRING_1_EXCEPTION, BOOLEAN_1_EXCEPTION, ARRAY_1_EXCEPTION,
                    ITERABLE_1_EXCEPTION };
            for (GetterWithException getter : getters) {
                String throwsClause = generateThrowsClause(IOException.class, getter.getPropertyName(),
                        getter.isBooleanType());
                String replacement = throwsClause + generateThrowsClause(SQLException.class,
                        getter.getPropertyName(), getter.isBooleanType());
                expectedContent = expectedContent.replace(throwsClause, replacement);
            }
        }
        assertThat(fileGeneratedFor(beanClass)).hasContent(expectedContent);
    }

    private String generateThrowsClause(Class<?> exception, String property, boolean booleanType) {
        String getter = (booleanType ? "is" : "get") + Character.toUpperCase(property.charAt(0))
                + property.substring(1);
        return "   * @throws " + exception.getName() + " if actual." + getter + "() throws one." + LINE_SEPARATOR;
    }

    @Test
    public void should_generate_assertion_for_classes_in_package() throws Exception {
        Set<Class<?>> classes = collectClasses("org.assertj.assertions.generator.data");
        for (Class<?> clazz : classes) {
            assertThat(clazz.isAnonymousClass()).as("check that <" + clazz.getSimpleName() + "> is not anonymous")
                    .isFalse();
            assertThat(clazz.isLocalClass()).as("check that " + clazz.getSimpleName() + " is not local").isFalse();
            assertThat(isPublic(clazz.getModifiers())).as("check that " + clazz.getSimpleName() + " is public")
                    .isTrue();
            logger.info("Generating assertions for {}", clazz.getName());
            final ClassDescription classDescription = converter.convertToClassDescription(clazz);
            File customAssertionFile = assertionGenerator.generateCustomAssertionFor(classDescription);
            logger.info("Generated {} assertions file -> {}", clazz.getSimpleName(),
                    customAssertionFile.getAbsolutePath());
        }
    }

    @Test
    public void should_generate_assertion_for_classes_in_package_using_provided_class_loader() throws Exception {
        ClassLoader customClassLoader = new MyClassLoader(Thread.currentThread().getContextClassLoader());
        Set<Class<?>> classes = collectClasses(customClassLoader, "org.assertj.assertions.generator.data");
        for (Class<?> clazz : classes) {
            assertThat(clazz.isAnonymousClass()).as("check that " + clazz.getSimpleName() + " is not anonymous")
                    .isFalse();
            assertThat(clazz.isLocalClass()).as("check that " + clazz.getSimpleName() + " is not local").isFalse();
            assertThat(isPublic(clazz.getModifiers())).as("check that " + clazz.getSimpleName() + " is public")
                    .isTrue();
            logger.info("Generating assertions for {}", clazz.getName());
            final ClassDescription classDescription = converter.convertToClassDescription(clazz);
            File customAssertionFile = assertionGenerator.generateCustomAssertionFor(classDescription);
            logger.info("Generated {} assertions file -> {}", clazz.getSimpleName(),
                    customAssertionFile.getAbsolutePath());
        }
    }

    @Test
    public void should_generate_assertion_for_classes_using_type_with_same_name() throws IOException {
        Class<?> clazz = ClassUsingDifferentClassesWithSameName.class;
        assertionGenerator.generateCustomAssertionFor(converter.convertToClassDescription(clazz));
        assertGeneratedAssertClass(ClassUsingDifferentClassesWithSameName.class,
                "ClassUsingDifferentClassesWithSameName.expected.txt");
    }

    static void assertGeneratedAssertClass(Class<?> clazz, String expectedAssertFile) {
        File expectedFile = new File("src/test/resources/" + expectedAssertFile).getAbsoluteFile();
        assertThat(fileGeneratedFor(clazz)).hasSameContentAs(expectedFile);
    }

    private static void assertAbstractGeneratedAssertClass(Class<?> clazz, String expectedAssertFile) {
        File expectedFile = new File("src/test/resources/" + expectedAssertFile).getAbsoluteFile();
        assertThat(abstractFileGeneratedFor(clazz)).hasSameContentAs(expectedFile);
    }

    private static String expectedContentFromTemplate(Class<?> clazz, String fileTemplate) throws IOException {
        String template = readFileToString(new File("src/test/resources/" + fileTemplate));
        String content = replace(template, "${nestedClass}Assert",
                getSimpleNameWithOuterClassNotSeparatedByDots(clazz) + "Assert");
        content = replace(content, "${nestedClass}", getSimpleNameWithOuterClass(clazz));
        return content;
    }

    private static File fileGeneratedFor(Class<?> clazz) {
        String dirName = TARGET_DIRECTORY + File.separatorChar
                + clazz.getPackage().getName().replace('.', File.separatorChar);
        String generatedFileName = getSimpleNameWithOuterClassNotSeparatedByDots(clazz) + ASSERT_CLASS_FILE_SUFFIX;
        return new File(dirName, generatedFileName);
    }

    private static File abstractFileGeneratedFor(Class<?> clazz) {
        String dirName = TARGET_DIRECTORY + File.separatorChar
                + clazz.getPackage().getName().replace('.', File.separatorChar);
        String generatedFileName = ABSTRACT_ASSERT_CLASS_PREFIX
                + getSimpleNameWithOuterClassNotSeparatedByDots(clazz) + ASSERT_CLASS_FILE_SUFFIX;
        return new File(dirName, generatedFileName);
    }

    class MyClassLoader extends ClassLoader {
        public MyClassLoader(ClassLoader parent) {
            super(parent);
        }
    }

}