为什么测试需要永远执行

时间:2019-09-04 14:33:00

标签: java testing

在构建我分叉的Maven项目时,它运行src / test中的几个测试类,其中一个测试类特别麻烦:TestWriteAndRead

尝试运行此类时,测试永远不会完成。

package regalowl.simpledatalib.sql;

import static org.junit.Assert.*;

import org.junit.Test;

import regalowl.simpledatalib.SimpleDataLib;
import regalowl.simpledatalib.TestLogger;
import regalowl.simpledatalib.sql.Field;
import regalowl.simpledatalib.sql.FieldType;
import regalowl.simpledatalib.sql.SQLManager;
import regalowl.simpledatalib.sql.Table;

public class TestWriteAndRead {
    @Test
    public void testCreateShutdownAndLoad() {
        SimpleDataLib sdl = new SimpleDataLib("test");
        sdl.initialize();
        sdl.setDebug(true);
        new TestLogger(sdl);
        SQLManager sm = sdl.getSQLManager();
        sm.setWriteTaskInterval(1L);
        sm.createDatabase();

        SQLWrite sw = sm.getSQLWrite();
        Table t = sm.addTable("hyperconomy_object_data");
        Field f = t.addField("ID", FieldType.INTEGER);f.setPrimaryKey();f.setAutoIncrement();
        f = t.addField("DATA", FieldType.TEXT);
        sm.saveTables();
        sw.writeSync(true);
        String statement = "DELETE FROM hyperconomy_object_data";
        sw.addToQueue(statement);
        sw.writeSyncQueue();
        sw.writeSync(false);


        statement = "INSERT INTO hyperconomy_object_data (ID, DATA) VALUES ('" + 1 + "', ?)";
        WriteStatement ws = new WriteStatement(statement, sdl);
        ws.addParameter("test");
        sw.addToQueue(ws);


        sm.shutDown();


        sdl.initialize();
        sdl.setDebug(true);
        new TestLogger(sdl);
        sm = sdl.getSQLManager();
        sm.createDatabase();
        SQLRead sr = sm.getSQLRead();
        QueryResult qr  = sr.select("SELECT * FROM hyperconomy_object_data WHERE ID = '1'");
        qr.next();
        assertTrue(qr.getString("DATA").equals("test"));
    }
}

不返回错误消息。测试开始,但从未结束

1 个答案:

答案 0 :(得分:0)

我已经从https://github.com/RegalOwl/SimpleDataLib中签出了您正在使用的项目 似乎在SQLWrite类内部的私有类WriteTask的getActiveStatements方法中具有并发性boohoo。

该测试不稳定,并且卡在了第43行的shutdown调用上。一旦通过调试,我看到synchronized在没有专用锁定对象的情况下使用,我立即怀疑并发问题。现在,研究这些我没有的类型的问题确实很耗时,但是我可以为您提供快速而又无意识的更改,以似乎可以解决该问题的原始代码:

private class WriteTask extends TimerTask {
    ReentrantLock activeStatementsLock = new ReentrantLock();

    //...keep the rest the same

    public ArrayList<WriteStatement> getActiveStatements() {
        synchronized (activeStatementsLock) {
            return writeData;
        }
    }
}

在方法上使用synchronized时,您基本上会执行与我的代码相同的操作,但是不是使用专用的activeStatementsLock对象,而是使用执行此方法的实例对象(等效使用synchronized (this))。但是,当您有几种这样的方法时,很容易遇到各种麻烦,例如死锁和诸如此类的问题,因此您可以通过拥有几个专用的锁定对象来对这些同步块进行分组。

在这种情况下,活动语句似乎与其他两个语句无关,并且将它们拆分可能是安全的,但是我不能保证。

请注意,我不知道问题的根本原因,因此我不确定此代码如何解决问题(或者我没有时间深入探讨此问题),并且更好的解决方案,您应该将此作为Bug提交给https://github.com/RegalOwl/SimpleDataLib/issues上的github问题,在那里,专门的贡献者将很乐意在自己的项目中解决问题。