How to unit test Java Hbase API

I am using the Java HBase API to get the 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; } 

It works great. Now I am writing Unit Test using the Mockito API. In my test class, I get java.langNullPointerException when it is when (table.get (any (Get.class))) thenReturn (result); 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 } 
+6
source share
3 answers

Edit

The 'Unit Test' should check and verify the specific 'code unit'. If this β€œcode unit” is dependent on external calls, then we mock these calls to return certain values.

If you do not call the "actual code unit" from your test case, then what is the point of unit testing the code. received it?

You should only make fun of external calls from the actual method, not the method itself.

So, I would make fun of:

 @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 } 
+3
source

You may have noticed that your code is poorly tested. The reason for poor testability is that your class does two things (create a table and execute a tuple). I would recommend that you break the class into two classes and introduce a class that creates a table into a class that performs a tuple.

This class creates a table:

 public class HTableFactory { private String tablename; public HTableFactory(String tablename) { this.tablename = tablename; } public HTable getTable() {} } 

Then your GetViewFromHbaseBolt class looks something like this:

 public class GetViewFromHbaseBolt extends BaseBasicBolt { private HTableFactory factory; private HTable table; public GetViewFromHbaseBolt(HTableFactory factory) {} @Override public void prepare(Map config, TopologyContext context) { table = factory.getTable(); } @Override public void execute(Tuple tuple, BasicOutputCollector collector) {} @Override public void declareOutputFields(OutputFieldsDeclarer declarer) {} } 

Now your GetViewFromHbaseBolt has the following dependencies:

  • HTableFactory
  • Tuple
  • BasicOutputCollector
  • OutputFieldsDeclarer

In your test class, you can mock these dependencies and embed them in GetViewFromHbaseBold .

0
source

Have you verified that you correctly initialized your poppies? I'm not an expert on Mockito, but it seems to me that you need to either install the test runner on the Mockito runner, or explicitly initialize the annotated mocks (@Mock). For example, see Using @Mock and @InjectMocks

My guess is that your "table" variable is null when you run the line that creates NullPointer.

0
source

Source: https://habr.com/ru/post/986329/


All Articles