vinsse2001
vinsse2001

Reputation: 47

how to test a method that uses clobs?

I have a method that compares the value of objects (as string, date, number...) and returns true or false depending of the result.

I've created a unit test for this method, but I'm having a problem testing the clob comparison, because with JUnit I don't have a connection, and if I use SerialClob to create two clobs (with the same content), I get objects with the same reference (so the part that compare clobs is not tested), I don't understand why two "new" generate the same object reference?

And another thing I don't understand, if I compare a string with a clob (identical values), the code that compares the clob is used, whereas instanceof is not supposed to be identical...!

What I expect is: when I compare 2 differents clobs, comparison as objects is false, as string (toString output) is false, it detects that objects are instanceof clobs, so convert them as string, and then compare string values.

Here is my code (simplified for example):

import java.io.*;
import java.sql.*;
import javax.sql.rowset.serial.*;

public class TestClob {
    
    public static void main(String[] args) throws SerialException, SQLException {
        boolean result;
        Object text1="abcdef", text2="abcdef";
        Clob clob1 = new SerialClob(((String) text1).toCharArray());
        Clob clob2 = new SerialClob(((String) text2).toCharArray());
        Clob clob3 = new SerialClob("abcdefg".toCharArray());

        System.out.println("TEST 1, basic string comparison");
        System.out.println("-------------------------------");
        result = haveSameValue(text1, text2);
        System.out.println("result: "+result);
        
        System.out.println("\nTEST 2, clob vs string");
        System.out.println("----------------------");
        result = haveSameValue(clob1, text1);
        System.out.println("result: "+result);
        
        System.out.println("\nTEST 3, different clobs objects but same value");
        System.out.println("----------------------------------------------");
        result = haveSameValue(clob1, clob2);
        System.out.println("result: "+result);
        
        System.out.println("\nTEST 4, different clobs");
        System.out.println("-----------------------");
        result = haveSameValue(clob1, clob3);
        System.out.println("result: "+result);
    } 
    
    public static boolean haveSameValue(Object obj1, Object obj2) {
        String sObj1, sObj2, sObj1Class, sObj2Class;
        boolean result = false;

        if (obj1!=null && obj2!=null) {
            sObj1Class = obj1.getClass().toString().toLowerCase();
            sObj2Class = obj2.getClass().toString().toLowerCase();
            System.out.println("  Objects class : sObj1Class="+sObj1Class+", sObj2Class="+sObj2Class);

            System.out.println("  OBJECT : obj1="+obj1+", obj2="+obj2+", => equal as object? "+obj1.equals(obj2));
            
            if (!obj1.equals(obj2)) {
                sObj1=obj1.toString();
                sObj2=obj2.toString();
                System.out.println("  STRING : sObj1="+sObj1+", sObj2="+sObj2+", => equal as string? "+sObj1.equals(sObj2));
                
                if (!sObj1.equals(sObj2)) {                 
                    if (obj1 instanceof java.sql.Clob || obj2 instanceof java.sql.Clob) {
                        sObj1 = ClobToString(obj1);
                        sObj2 = ClobToString(obj2);
                        System.out.println("  CLOB : sObj1="+sObj1+", sObj2="+sObj2+" => equal as clob? "+sObj1.equals(sObj2));
                        result = sObj1.equals(sObj2);
                    }
                    
                    // other comparisons (as a date, timestamp, number...)
                }
            }
        }
        
        return result;
    }
    
    public static String ClobToString(Object object) {
        if (object==null) {
            return null;
        }
        else if (object instanceof java.sql.Clob) {
            StringBuilder sb = new StringBuilder();
            try {
                Reader reader = ((java.sql.Clob) object).getCharacterStream();
                BufferedReader br = new BufferedReader(reader);

                String line;
                while(null != (line = br.readLine())) {
                    sb.append(line);
                }
                br.close();
                return sb.toString();
            }
            catch (Exception e) {
                System.out.println("error : "+e.getMessage());
                return object.toString();
            }
        }
        else {
            return object.toString();
        }
    }
}

and here is the output:

TEST 1, basic string comparison
-------------------------------
  Objects class : sObj1Class=class java.lang.string, sObj2Class=class java.lang.string
  OBJECT : obj1=abcdef, obj2=abcdef, => equal as object? true
result: true

TEST 2, clob vs string
----------------------
  Objects class : sObj1Class=class javax.sql.rowset.serial.serialclob, sObj2Class=class java.lang.string
  OBJECT : obj1=javax.sql.rowset.serial.SerialClob@df59efc3, obj2=abcdef, => equal as object? false
  STRING : sObj1=javax.sql.rowset.serial.SerialClob@df59efc3, sObj2=abcdef, => equal as string? false
  CLOB : sObj1=abcdef, sObj2=abcdef => equal as clob? true
result: true

TEST 3, different clobs objects but same value
----------------------------------------------
  Objects class : sObj1Class=class javax.sql.rowset.serial.serialclob, sObj2Class=class javax.sql.rowset.serial.serialclob
  OBJECT : obj1=javax.sql.rowset.serial.SerialClob@df59efc3, obj2=javax.sql.rowset.serial.SerialClob@df59efc3, => equal as object? true
result: true

TEST 4, different clobs
-----------------------
  Objects class : sObj1Class=class javax.sql.rowset.serial.serialclob, sObj2Class=class javax.sql.rowset.serial.serialclob
  OBJECT : obj1=javax.sql.rowset.serial.SerialClob@df59efc3, obj2=javax.sql.rowset.serial.SerialClob@bd7d1c2, => equal as object? false
  STRING : sObj1=javax.sql.rowset.serial.SerialClob@df59efc3, sObj2=javax.sql.rowset.serial.SerialClob@bd7d1c2, => equal as string? false
  CLOB : sObj1=abcdef, sObj2=abcdefg => equal as clob? false
result: false

Upvotes: 0

Views: 64

Answers (1)

Progman
Progman

Reputation: 19555

The variables clob1 and clob2 are referencing different objects, since new objects are created with the new keyword. However, these objects have the same "value" in them. The SerialClob.equals() method is defined in such a way, that two SerialClob instances are equal to each other, when they have the same value:

Compares this SerialClob to the specified object. The result is true if and only if the argument is not null and is a SerialClob object that represents the same sequence of characters as this object.

This is the case here, they have the same value "abcdef" in them. This means that the if block

if (!obj1.equals(obj2)) {
    ...
}

is not entered. And therefore, no further check is executed since you already know they are "equal".

Upvotes: 2

Related Questions