Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to unit test Java Hbase API

I am using the Java HBase API to get a value from Hbase. This is my code.

public class GetViewFromHbaseBolt extends BaseBasicBolt {

private HTable table;
private String zkQuorum;
private String zkClientPort;
private String tableName;

public GetViewFromHbaseBolt(String table, String zkQuorum,
        String zkClientPort) {
    this.tableName = table;
    this.zkQuorum = zkQuorum;
    this.zkClientPort = zkClientPort;
}

@Override
public void prepare(Map config, TopologyContext context) {
    try {
        table = getHTable();
    } catch (IOException e) {

        e.printStackTrace();
    }
}

@Override
public void execute(Tuple tuple, BasicOutputCollector collector) {
    try {
        if (tuple.size() > 0) {

            Long dtmid = tuple.getLong(0);

            byte[] rowKey = HBaseRowKeyDistributor.getDistributedKey(dtmid);
            Get get = new Get(rowKey);
            get.addFamily("a".getBytes());

            Result result = table.get(get);
            System.out.println(result);
            byte[] bidUser = result.getValue("a".getBytes(),
                    "co_created_5076".getBytes());
            collector.emit(new Values(dtmid, bidUser));
        }

    } catch (IOException e) {
        e.printStackTrace();

    }

}

@Override
public void declareOutputFields(OutputFieldsDeclarer declarer) {

    declarer.declare(new Fields("dtmi", "bidUser"));

}

// setting up the conections for Hbase
protected HTable getHTable() throws IOException {
    HTable table = null;
    Configuration conf;
    conf = HBaseConfiguration.create();
    conf.set("hbase.zookeeper.property.clientPort", zkClientPort);
    conf.set("hbase.zookeeper.quorum", zkQuorum);

    table = new HTable(conf, tableName);

    return table;
}

This works fine. Now I am writing a Unit Test using the Mockito API. On my test class I am getting a java.langNullPointerException when this when(table.get(any(Get.class))).thenReturn(result); is called.

   public class GetViewFromHbaseBoltTest {

@Mock
private TopologyContext topologyContext;
@Mock
private  HTable table;
//HTable table = mock(HTable.class);


@Test
public void testExecute() throws IOException {

    long dtmId = 350000000770902930L;
    final byte[] COL_FAMILY = "a".getBytes();
    final byte[] COL_QUALIFIER = "co_created_5076".getBytes();

    // A mock tuple with a single dtmid
    Tuple tuple = mock(Tuple.class);
    when(tuple.size()).thenReturn(1);
    when(tuple.getLong(0)).thenReturn(dtmId);

    List<KeyValue> kvs = new ArrayList<KeyValue>();
    kvs.add(new KeyValue(COL_FAMILY, COL_QUALIFIER, Bytes
            .toBytes("ExpedtedBytes")));
    Result result = new Result(kvs);


    when(table.get(any(Get.class))).thenReturn(result);

    BasicOutputCollector collector = mock(BasicOutputCollector.class);

    GetViewFromHbaseBolt bolt = mock(GetViewFromHbaseBolt.class);
    // Execute the bolt.
    bolt.execute(tuple, collector);

    ArgumentCaptor<Values> valuesArg = ArgumentCaptor
            .forClass(Values.class);
    verify(collector).emit(valuesArg.capture());
    ArrayList<Object> d = valuesArg.getValue();

// verify

}
like image 770
danilo Avatar asked Apr 30 '15 20:04

danilo


1 Answers

Edit

'Unit Test' is to verify, and validate a particular 'unit of code'. If that 'unit of code' depends on external calls, then we mock those calls to return certain values.

If you don't invoke the 'actual unit of code' from your test case, then what is the point in unit testing the code. got it?

You should mock only external calls from actual method, not the actual method itself.

So I would mock like:

@Mock
private HBaseRowKeyDistributor hDist;

@Mock
private HTable table;

@Test
public void sampleTest(){

    //Mock data and external calls

    final byte [] COL_FAMILY = "a".getBytes();
    final byte [] COL_QUALIFIER = "co_created_5076".getBytes();

    List<KeyValue> kvs =new ArrayList<KeyValue>();
    kvs.add(new KeyValue(COL_FAMILY, COL_QUALIFIER,
                           Bytes.toBytes("ExpedtedBytes")));
     Result result = new Result(kvs);

     byte[] rowKey = "Hello".getBytes();
     when(hdist.getDistributedKey(anyString()).thenReturn(rowKey);

     when(table.get(any(Get.class))).thenReturn(result);

     //Call the actual method
     calloriginalUnitTestingMethod();


     //Now Verify the result using Mockito verify like
     verify(...)

     //You could also intercept the attributes

}
like image 113
K139 Avatar answered Oct 21 '22 16:10

K139