测试在IDE中传递但在TeamCity中失败

时间:2016-08-04 08:12:15

标签: java junit mockito powermock

我有一个必须测试的课程:

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中传递,但是当我在存储库中进行推送时,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

我在我的问题中为这么多代码道歉。

2 个答案:

答案 0 :(得分:1)

你可能有相互冲突的Powermock / Mockito版本。 检查您当地的maven repo以获取版本,并删除旧版本 在你的pom中和/或更新包含它的其他依赖项。

使用以下命令检查项目的根目录:

mvn dependency:tree -Dverbose -Dincludes=NAME_OF_DEPENDENCY

答案 1 :(得分:1)

TeamCity仓库中的依赖库与本地仓库存在冲突。

确认TC版本使用的是当地正在使用的完全相同版本的Powermock。

可能会传递旧版本。

mvn dependency:tree -Dverbose

这将列出所有可解析的依赖项。看看是否有不同版本的Powermock。然后,您可以使用pom.xml中的exclude / exclusions标记来阻止它们被拉入。