Тест пройден в IDE, но не прошел в TeamCity

У меня есть класс, который я должен был проверить:

package com.mycompany.openapi.cms.core.support.liquibase;

import liquibase.change.custom.CustomTaskChange;
import liquibase.database.Database;
import liquibase.database.jvm.JdbcConnection;
import liquibase.exception.CustomChangeException;
import liquibase.exception.SetupException;
import liquibase.exception.ValidationErrors;
import liquibase.resource.ResourceAccessor;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.sql.Statement;
import java.util.Set;

public class ApplySqlFileIfExistsChange implements CustomTaskChange {

    private final org.slf4j.Logger logger = LoggerFactory.getLogger(getClass());

    private String file;
    private ResourceAccessor resourceAccessor;

    @Override
    public void execute(Database database) throws CustomChangeException {
        JdbcConnection databaseConnection = (JdbcConnection) database.getConnection();
        try {
            Set<InputStream> files = resourceAccessor.getResourcesAsStream(file);
            if(files != null){
                for (InputStream inputStream : files) {
                    BufferedReader in = new BufferedReader(
                            new InputStreamReader(inputStream));
                    String str;
                    String sql;
                    StringBuilder sqlBuilder = new StringBuilder("");
                    while ((str = in.readLine()) != null) {
                        sqlBuilder.append(str).append(" ");
                    }
                    in.close();
                    sql = sqlBuilder.toString().trim();
                    if(StringUtils.isEmpty(sql)){
                        return;
                    }
                    Statement statement = databaseConnection.createStatement();
                    statement.execute(sql);
                    statement.close();
                }
            }
        } catch (FileNotFoundException e) {
            logger.error(e.getMessage(), e);
        } catch (Exception e) {
            throw new CustomChangeException(e);
        }
    }

    public String getFile() {
        return file;
    }

    public void setFile(String file) {
        this.file = file;
    }

    @Override
    public void setFileOpener(ResourceAccessor resourceAccessor) {
        this.resourceAccessor = resourceAccessor;
    }
}

Я написал тест:

package com.mycompany.openapi.cms.core.support.liquibase;

import com.google.common.collect.Sets;
import liquibase.database.Database;
import liquibase.database.jvm.JdbcConnection;
import liquibase.resource.ResourceAccessor;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.sql.Statement;

import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.verify;
import static org.powermock.api.mockito.PowerMockito.*;

@RunWith(PowerMockRunner.class)
@PrepareForTest({LoggerFactory.class})
public class TestApplySqlFileIfExistsChange {

    @InjectMocks
    ApplySqlFileIfExistsChange applySqlFileIfExistsChange;

    @Mock
    private ResourceAccessor resourceAccessor;

    @Mock
    private JdbcConnection jdbcConnection;

    @Mock
    private Database database;

    @Mock
    Statement statement;

    @BeforeClass
    public static void setUpClass() {
        mockStatic(LoggerFactory.class);
        when(LoggerFactory.getLogger(ApplySqlFileIfExistsChange.class)).thenReturn(mock(Logger.class));
    }

    @Before
    public void setUp() throws Exception {
        when(database.getConnection()).thenReturn(jdbcConnection);

        InputStream inp1, inp2;
        inp1 = new ByteArrayInputStream("FirstTestQuery".getBytes(StandardCharsets.UTF_8));
        inp2 = new ByteArrayInputStream("SecondTestQuery".getBytes(StandardCharsets.UTF_8));

        when(resourceAccessor.getResourcesAsStream(anyString())).thenReturn(Sets.newHashSet(inp1, inp2));
        when(jdbcConnection.createStatement()).thenReturn(statement);
    }

    @Test
    public void execute() throws Exception {
        applySqlFileIfExistsChange.execute(database);
        verify(statement).execute("FirstTestQuery");
        verify(statement).execute("SecondTestQuery");
    }

}

Проблема в том, что вышеприведенный тест прошел в моей среде IDE, но когда я делаю push в репозиторий, сборка TeamCity не удалась в моем тесте. Я не могу понять, почему, потому что код одинаковый в обоих местах. Вот трассировка стека в TeamCity:

java.lang.IllegalStateException: Failed to transform class with name org.slf4j.LoggerFactory. Reason: java.io.IOException: invalid constant type: 15
    at org.powermock.core.classloader.MockClassLoader.loadMockClass(MockClassLoader.java:267)
    at org.powermock.core.classloader.MockClassLoader.loadModifiedClass(MockClassLoader.java:180)
    at org.powermock.core.classloader.DeferSupportingClassLoader.loadClass(DeferSupportingClassLoader.java:70)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
    at java.lang.Class.forName0(Native Method)
    at java.lang.Class.forName(Class.java:348)
    at sun.reflect.generics.factory.CoreReflectionFactory.makeNamedType(CoreReflectionFactory.java:114)
    at sun.reflect.generics.visitor.Reifier.visitClassTypeSignature(Reifier.java:125)
    at sun.reflect.generics.tree.ClassTypeSignature.accept(ClassTypeSignature.java:49)
    at sun.reflect.annotation.AnnotationParser.parseSig(AnnotationParser.java:439)
    at sun.reflect.annotation.AnnotationParser.parseClassValue(AnnotationParser.java:420)
    at sun.reflect.annotation.AnnotationParser.parseClassArray(AnnotationParser.java:724)
    at sun.reflect.annotation.AnnotationParser.parseArray(AnnotationParser.java:531)
    at sun.reflect.annotation.AnnotationParser.parseMemberValue(AnnotationParser.java:355)
    at sun.reflect.annotation.AnnotationParser.parseAnnotation2(AnnotationParser.java:286)
    at sun.reflect.annotation.AnnotationParser.parseAnnotations2(AnnotationParser.java:120)
    at sun.reflect.annotation.AnnotationParser.parseAnnotations(AnnotationParser.java:72)
    at java.lang.Class.createAnnotationData(Class.java:3521)
    at java.lang.Class.annotationData(Class.java:3510)
    at java.lang.Class.getAnnotation(Class.java:3415)
    at org.junit.internal.MethodSorter.getDeclaredMethods(MethodSorter.java:52)
    at org.junit.internal.runners.TestClass.getAnnotatedMethods(TestClass.java:45)
    at org.junit.internal.runners.MethodValidator.validateTestMethods(MethodValidator.java:71)
    at org.junit.internal.runners.MethodValidator.validateStaticMethods(MethodValidator.j

Прошу прощения за такое количество кода в моем вопросе.


person Sergey Luchko    schedule 04.08.2016    source источник
comment
получить последние источники / зависимости, ту же версию инструмента тестирования?   -  person lordkain    schedule 04.08.2016
comment
Да, мы используем maven и pom.xml абсолютно идентичны.   -  person Sergey Luchko    schedule 04.08.2016
comment
Похоже на дубликат: stackoverflow.com/questions/32854688/   -  person Arthur Zagretdinov    schedule 04.08.2016


Ответы (2)


Вероятно, у вас конфликтующие версии Powermock/Mockito. Проверьте версии в своем локальном репозитории maven и избавьтесь от более старых версий в вашем pom и/или обновите другую зависимость, которая включала ее.

Проверьте корень проекта с помощью:

mvn dependency:tree -Dverbose -Dincludes=NAME_OF_DEPENDENCY
person Alim Özdemir    schedule 04.08.2016

У вас конфликт зависимых библиотек в репозитории TeamCity и вашего локального репозитория.

Убедитесь, что сборка TC использует ту же версию Powermock, что и ваша локальная версия.

Может быть транзитивно включена более старая версия.

mvn dependency:tree -Dverbose

Это перечислит все разрешимые зависимости. Посмотрите, есть ли разные версии Powermock. Затем вы можете предотвратить их втягивание, используя тег exclude/exclusions в файле pom.xml.

person UserF40    schedule 04.08.2016
comment
Я упомянул об этом, это была моя первая мысль о pom.xml, но они одинаковы. - person Sergey Luchko; 04.08.2016
comment
Ключевое слово - транзитивность. Возможно, его подтягивает другая зависимость, а затем TC загружает путь к классу по-другому, и поэтому используется другая версия. - person UserF40; 04.08.2016
comment
Может быть ты прав. попробую что-нибудь с этим сделать. - person Sergey Luchko; 04.08.2016