Faking Method parameters using Mockito/PowerMockito

主宰稳场 提交于 2019-12-11 10:56:03

问题


public class FakeExcelSheet implements Sheet
{
     private final Map<Integer, FakeExcelRow> fakeSheet = new HashMap<Integer, FakeExcelRow>();

     @Override
     public Row createRow(int rowNum)
     {
          Row row = new FakeExcelRow(rowNum, fakeSheet);
          fakeSheet.put(rowNum, (FakeExcelRow)row);
          return row;
     }

     @Override
     public Row getRow(int rowNum)
     {
          if (fakeSheet.get(rowNum) != null)
          {
               return fakeSheet.get(rowNum);
          }
          else
          {
               return createRow(rowNum);
          }

     }

     /**Other unimplemented methods of Apache POI class Sheet**/ 
}

public class FakeExcelRow implements Row
{
    private int rowNum;
    private Map<Integer, FakeExcelRow> sheet;
    private List<Object> cellList = new LinkedList<Object>();

    public FakeExcelRow(int rowNum , Map<Integer,FakeExcelRow> sheet)
    {
          this.rowNum = rowNum;
          this.sheet = sheet;
    }

    @Override
    public Cell createCell(int colNum)
    {
         return new FakeExcelCell(colNum, rowNum, sheet);
    }

    /**Other unimplemented methods of Apache POI class Row**/
}

public class FakeExcelCell implements Cell
{
      private int colNum;
      private int rowNum;
      private Map<Integer, FakeExcelRow> sheet;

      public FakeExcelCell(int colNum, int rowNum, Map<Integer, FakeExcelRow> sheet)
      {
          this.colNum = colNum;
          this.rowNum = rowNum;
          this.sheet = sheet;
      }

      public void setCellValue(String value)
      {
           if(sheet != null)
           {
                FakeExcelRow fakeExcelRow = sheet.get(rowNum);
                List<Object> cellList = fakeExcelRow.getCellList();
                cellList.add(value);
           }
      }

      /**Other unimplemented methods of Apache POI class Cell**/
}

I have to test the my class Service which is using class ExcelWriter's protected method writeToCell like this :

public class ServiceImpl
{
     ........
     .
     .
     private ExcelWriter excelWriter;
     private Sheet sheet;
     private void handleRequest()
     {

           while("Till there are more rows")
           {
           excelWriter.writeDetailsForCategory(List<String> listOfItems)
           }
     }
 }

The ExcelWriter Class is designed like this:

public class ExcelWriter()
{
     protected Sheet sheet;
     public void writeDetailsForCategory(List<String> listOfItems)
     {
           for(String item : listOfItems)
           {
                 writeToCell(rowNum, columnNum, value, sheet);
                 columnNum++;
           }
     }
}

The writeToCell() method is designed with protected access modifier:

protected void writeCell(int rowNum, int colNum, String value, Sheet sheet)
{

    if (value == null)
    {
        return;
    }

    Row row = sheet.getRow(rowNum);

    if (row == null)
    {
        row = sheet.createRow(rowNum);
    }

    Cell cell = row.createCell(colNum);
    cell.setCellValue(value);

}

I have to unit test the handleRequest method of the class ServiceImpl which uses ExcelWriter's writeDetailsForCategory , which is using protected method writeToCell. I have pass the FakeExcelSheet in the writeToCell method.I will assert on the values of the Map <Object, FakeExcelRow> after this. How should I pass in the fakeExcelSheet parameter in protected writeToCell method? My constraints are that I can use Mockito or PowerMockito only.


回答1:


Continuing on from my other answer, you could replace the specific ExcelWriter with a StringGridWriter, which writes to a given StringGrid. It does not know or care that it is excel.

public final class StringGridWriter() {
     private final StringGrid grid;

     public StringGridWriter(StringGrid grid) {
        this.grid = grid;
     }

     public void writeDetailsForCategory(List<String> listOfItems) {
           for(String item : listOfItems) {
                 grid.writeToCell(rowNum, columnNum, value);
                 columnNum++;
           }
     }
}

Usage in service:

public class ServiceImpl {
     ........
     .
     .
     private final StringGridWriter gridWriter;

     public ServiceImpl(StringGridWriter gridWriter) {
         this.gridWriter = gridWriter;
     }

     private void handleRequest() {    
           while("Till there are more rows"){
             gridWriter.writeDetailsForCategory(List<String> listOfItems)
           }
     }
 }

And this is how you'd assign to it to use it:

Sheet theApacheSheet = ...;

StringGrid grid = new ApacheSheetStringGrid(theApacheSheet);

StringGridWriter writer = new StringGridWriter(grid);

ServiceImpl service = new ServiceImpl(writer);

Where ApacheSheetStringGrid is as per my other answer. So now, even the ServiceImpl has no idea that this is using excel. This injection of dependencies is the Dependency Inversion Principle in practice.

See how I rapidly get away from the complicated excel interfaces and boil it down to just an abstraction, a subset of functionality, which is only the interface my client wants (Interface Segregation Principle), which makes it both easy to test, and easy to replace with other implementations. By not abstracting you are tightly coupling your code to the apache excel implementation.



来源:https://stackoverflow.com/questions/36667172/faking-method-parameters-using-mockito-powermockito

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!