@Override
  public boolean processRow( StepMetaInterface smi, StepDataInterface sdi ) throws KettleException {
    Object[] r = null;
    r = getRow();

    if ( r == null ) { // no more rows to be expected from the previous step(s)
      setOutputDone();
      return false;
    }

    if ( data.firstRow ) {
      // The output meta is the original input meta + the
      // additional constant fields.

      data.firstRow = false;
      data.outputMeta = getInputRowMeta().clone();
      meta.getFields( data.outputMeta, getStepname(), null, null, this, repository, metaStore );
    }

    // Add the constant data to the end of the row.
    r = RowDataUtil.addRowData( r, getInputRowMeta().size(), data.getConstants().getData() );

    putRow( data.outputMeta, r );

    if ( log.isRowLevel() ) {
      logRowlevel( BaseMessages.getString(
        PKG, "Constant.Log.Wrote.Row", Long.toString( getLinesWritten() ), getInputRowMeta().getString( r ) ) );
    }

    if ( checkFeedback( getLinesWritten() ) ) {
      if ( log.isBasic() ) {
        logBasic( BaseMessages.getString( PKG, "Constant.Log.LineNr", Long.toString( getLinesWritten() ) ) );
      }
    }

    return true;
  }
@Test
  public void testProcessRow_fail() throws Exception {

    doReturn( null ).when( constantSpy ).getRow();
    doReturn( null ).when( constantSpy ).getInputRowMeta();

    boolean success = constantSpy.processRow( constantMeta, constantData );
    assertFalse( success );
  }