首页 > 解决方案 > Has anyone done a FitNesse TEST that queries to REAL Database? I can't make Fitnesse connect successfully

问题描述

I'm asking because ALL examples I find in Google, are the same from the Fitnesse tutorial: a very simple query to a list or array in memory, NOT A REAL Database.

Yes, Fixtures never have to deal with that, but how am I supposed to test my fixtures if I can't even make the connection to the DB in a simulation of an "API"?

What I'm trying to simulate is the call from a FitNesse Fixture to query in Java into a PostgreSQL database/table. In this simple example I'm trying to obtain, at least one column from one row, in one table. When I execute the code, it runs perfectly by it's own. The problem is when trying to execute from Fitnesse through the fixture. It always fails with a ClassNotFoundException, when calling the JDBC driver. This doesn't happen by running the code by it's own.

Here is the code that does the query:

package queriespackage;

import java.sql.*;

public class testQuery01 {

    public static Connection openDBConnection(){
        Connection connectionString = null;
        try {
            String dbhost = "SOMEURL";//Redacted
            String port = "SOMEPORT";//Redacted
            String dbname = "THEDBNAME";//Redacted
            String username = "SOMEUSER";//Redacted
            String password = "SOMEPASSWORD";//Redacted
            String driverJDBC = "org.postgresql.Driver";

            Class.forName(driverJDBC);
            connectionString = DriverManager.getConnection("jdbc:postgresql://" + dbhost + ":" + port + "/" + dbname,username,password);
            connectionString.setAutoCommit(false);
        } catch (SQLException e) {
            e.printStackTrace(System.err);
            System.exit(0);
        }  catch (Exception e) {
            System.err.println( e.getClass().getName()+": "+ e.getMessage() );
            System.exit(0);
        };
        return connectionString;
    };

    public static ResultSet executeQuery(Connection connectionString, int intAccountId) throws SQLException{

        Statement querySession = connectionString.createStatement();
        //The query string
        String queryString = "SELECT DISTINCT "
                + "account_search.account_id,"
                + "account_search.account_name"
                + " FROM account_search "
                + " WHERE"
                + " account_search.account_id = "+ intAccountId
                + "LIMIT 1";

        ResultSet queryResult = querySession.executeQuery(queryString);
        return queryResult; 
    };

    public static String processQueryResult(ResultSet queryResult) throws SQLException{
        String strQueryValueReturned = null;
        while (queryResult.next()) {
            strQueryValueReturned = queryResult.getString("account_name");
        };
        return strQueryValueReturned;       
    };

    public static boolean closeDBConnection(Connection connectionString){
        try {
            if(connectionString!=null){
                connectionString.close();
            }
        } catch (SQLException e) {
            System.err.println( e.getClass().getName()+": "+ e.getMessage() );
            System.exit(0);
        };
        return true;
    };

    public static String testQuery(int intAccountId) throws SQLException, ClassNotFoundException{
        boolean bolConnectionStatus = false;
        String strValueReturned = null;

        Connection connectionString = openDBConnection();

        if(connectionString != null){
            ResultSet qryQueryResult = executeQuery(connectionString, intAccountId);
            strValueReturned = processQueryResult(qryQueryResult);
            bolConnectionStatus = closeDBConnection(connectionString);
            if(!bolConnectionStatus){
                System.exit(0);
            }
        }else{
            System.exit(0);
        };
        return strValueReturned;
    };

};

If I add a Main method to that code, passing it the argument value for "intAccountId", it successfully returns the name of the account "account_name", just as expected.

Now here's the Fixture that should be called by the FitNesse test:

package fixturespackage;

import java.sql.SQLException;
import queriespackage.testQuery01;

public class testFixture01{

    private int Int_AccountId;

    //Fixture Constructor (setter)
    public testFixture01(int Int_AccountId){
        this.Int_AccountId = Int_AccountId;
    };  


    public String query() throws SQLException, ClassNotFoundException{
        return testQuery01.testQuery(Int_AccountId);
    };
};

Just as the FitNesse guide says, there must be a "query" method, that does the actual call to the interface in the DB. I had to add a constructor instead of the "setter", because FitNesse actually demands it: "Could not invoke constructor for fixturepackage.testFixture01"

Here's the FitNesse page:

!***> System Variables
!define TEST_SYSTEM {slim}
!path C:\FitnessTest\bin
*!

|Query: fixturespackage.testFixture01|21 |
|Str_AccountName                         |
|SomeName                                |

Here's a Screenshot of my BuildPath, so you can see I have the JDBC Library for Java 8, JDK 1.8, JRE 1.8... and the "org.postgresql.Driver.class" is included in the project.

org.postgresql.Driver.class

This is the error I receive, when running from FitNesse:

Line 26 is where the Exception is catched if JDBC is not loaded.

This is the error I get, when debugging the line where FitNesse failed by using Inspect tool:

Defined as: String driverJDBC =

... and YES, I also tried by hard coding the name of the JDBC:

enter image description here

I have searched a lot for a REAL LIFE example, both here, the FitNesse Guide and Google.

The FitNesse Guide might be extensive, but let's be sincere, it's full of "dirty word here", unrealistic and incomplete examples and missing a lot of information.

So, asking again, has anyone done a REAL LIFE test making queries, using FitNesse, that could help me find out what am I doing wrong?

标签: javapostgresqlfitnesse

解决方案


我不得不承认我只用 FitNesse 进行了有限的数据库测试,但我已经使用它们(查询 DB2)。我没有使用查询表(或编写我自己的夹具来查询),而是将jdbcslim与脚本表和场景结合使用。

无法找到驱动程序类的事实表明,尽管 jar 存在于 IDE 的类路径中,但在 FitNesse 运行您的夹具代码时它不可用。

我注意到您将类路径指定为 wiki 中的单个目录。在 Java 中,这意味着所有类文件都应该在该目录中(作为 .class 文件,在其定义的包的正确子目录中)。它不会拾取该目录中的任何 jar(或 zip)。您是否将数据库驱动程序的 jar解压到该目录?如果没有,您需要!path使用数据库驱动程序添加一条指向 jar 的行(因此包括文件名的整个路径)。

现在列出你需要的每个 jar 很快就会变得很麻烦,所以你也可以使用通配符。我倾向于将我需要的所有 jar 复制到一个目录中,该目录还包含我的夹具 .class 文件,并添加!path一行加载该目录中的所有 jar。因此,如果您还将数据库驱动程序复制到您的问题目录中,您可以确保它和您自己的固定装置可以通过

!path C:\FitnessTest\bin
!path C:\FitnessTest\bin\*.jar

推荐阅读