问题
I created a word-document with apache-poi (poi-ooxml version 3.15) and now I want to write unit tests for my classes. What is the best way to do that? We're using mockito(2.15.0) in our project.
This is one of the classes I'm trying to write test for:
@Component
public class ProffesionalSumaryService {
public void populateDocumentWithProfileSkills(XWPFDocument document, ExportProfileDTO profileData){
XWPFTable antet = document.createTable();
antet.getCTTbl().getTblPr().getTblBorders().getBottom().setColor(COLOR_OF_TABLE_BORDERS);
antet.getCTTbl().getTblPr().getTblBorders().getRight().setColor(COLOR_OF_TABLE_BORDERS);
antet.getCTTbl().getTblPr().getTblBorders().getLeft().setColor(COLOR_OF_TABLE_ANTET_BACKGROUND);
antet.getCTTbl().getTblPr().getTblBorders().getTop().setColor(COLOR_OF_TABLE_ANTET_BACKGROUND);
CTTblWidth ctTblWidth = antet.getCTTbl().getTblPr().getTblW();
ctTblWidth.setType(STTblWidth.PCT);
ctTblWidth.setW(BigInteger.valueOf(6*TWIPS_PER_INCH));
XWPFTableRow antetRow = antet.getRow(0);
antetRow.getCell(0).removeParagraph(0);
XWPFParagraph professionalSkills = antetRow.getCell(0).addParagraph();
setStyles(professionalSkills.createRun() , FONT_CALIBRI ,SUBTITLE_FONT_SIZE , COLOR_FORTECH , "Professional Summary" , true, false);
antetRow.getCell(0).setColor(COLOR_OF_TABLE_ANTET_BACKGROUND);
XWPFParagraph paragraphSkills = document.createParagraph();
XWPFTable skillsTable = document.createTable();
skillsTable.getCTTbl().getTblPr().getTblBorders().getBottom().setColor(COLOR_OF_TABLE_BORDERS);
skillsTable.getCTTbl().getTblPr().getTblBorders().getTop().setColor(COLOR_OF_TABLE_BORDERS);
skillsTable.getCTTbl().getTblPr().getTblBorders().getLeft().setColor(COLOR_OF_TABLE_BORDERS);
skillsTable.getCTTbl().getTblPr().getTblBorders().getRight().setColor(COLOR_OF_TABLE_BORDERS);
skillsTable.getCTTbl().addNewTblGrid().addNewGridCol().setW(BigInteger.valueOf(COLUMN_WIDTH_SMALL));
skillsTable.getCTTbl().getTblGrid().addNewGridCol().setW(BigInteger.valueOf(COLUMN_WIDTH_BIG));
XWPFTableRow projectSkillsRow = skillsTable.getRow(0);
XWPFParagraph _skills = projectSkillsRow.getCell(0).addParagraph();
setStyles(_skills.createRun(), FONT_CALIBRI , FONT_SIZE_NORMAL, COLOR_FORTECH , "Skills" , false, false);
projectSkillsRow.createCell();
try{
setSkillsBulletList(profileData.getSkillList(),document,projectSkillsRow);
}catch(XmlException e){
throw new RestExceptions.HeaderError();
}
}
protected void setSkillsBulletList(List<SkillEntity> skillEntities, XWPFDocument document, XWPFTableRow projectSkillsRow) throws XmlException {
String cTAbstractNumBulletXML =
"<w:abstractNum xmlns:w=\"http://schemas.openxmlformats.org/wordprocessingml/2006/main\" w:abstractNumId=\"0\">"
+ "<w:multiLevelType w:val=\"hybridMultilevel\"/>"
+ "<w:lvl w:ilvl=\"0\"><w:start w:val=\"1\"/><w:numFmt w:val=\"bullet\"/><w:lvlText w:val=\"\"/><w:lvlJc w:val=\"left\"/><w:pPr><w:ind w:left=\"720\" w:hanging=\"360\"/></w:pPr><w:rPr><w:rFonts w:ascii=\"Symbol\" w:hAnsi=\"Symbol\" w:hint=\"default\"/></w:rPr></w:lvl>"
+ "<w:lvl w:ilvl=\"1\" w:tentative=\"1\"><w:start w:val=\"1\"/><w:numFmt w:val=\"bullet\"/><w:lvlText w:val=\"o\"/><w:lvlJc w:val=\"left\"/><w:pPr><w:ind w:left=\"1440\" w:hanging=\"360\"/></w:pPr><w:rPr><w:rFonts w:ascii=\"Courier New\" w:hAnsi=\"Courier New\" w:cs=\"Courier New\" w:hint=\"default\"/></w:rPr></w:lvl>"
+ "<w:lvl w:ilvl=\"2\" w:tentative=\"1\"><w:start w:val=\"1\"/><w:numFmt w:val=\"bullet\"/><w:lvlText w:val=\"\"/><w:lvlJc w:val=\"left\"/><w:pPr><w:ind w:left=\"2160\" w:hanging=\"360\"/></w:pPr><w:rPr><w:rFonts w:ascii=\"Wingdings\" w:hAnsi=\"Wingdings\" w:hint=\"default\"/></w:rPr></w:lvl>"
+ "</w:abstractNum>";
XWPFRun run;
CTNumbering cTNumbering = CTNumbering.Factory.parse(cTAbstractNumBulletXML);
CTAbstractNum cTAbstractNum = cTNumbering.getAbstractNumArray(0);
XWPFAbstractNum abstractNum = new XWPFAbstractNum(cTAbstractNum);
XWPFNumbering numbering = document.createNumbering();
BigInteger abstractNumID = numbering.addAbstractNum(abstractNum);
BigInteger numID = numbering.addNum(abstractNumID);
projectSkillsRow.getCell(1).removeParagraph(0);
if(skillEntities.size() != 0)
for (SkillEntity skill : skillEntities) {
XWPFParagraph item = projectSkillsRow.getCell(1).addParagraph();
item.setNumID(numID);
run = item.createRun();
run.setText(skill.getSkillDescriptionEntity().getName() + " - " + SKILL_SCORES.values()[skill.getSkillScore()]);
}
else {
XWPFParagraph item = projectSkillsRow.getCell(1).addParagraph();
run = item.createRun();
run.setText("No skills");
}
}
private static void setStyles(XWPFRun run , String fontFamily , int fontSize , String colorRGB , String text , boolean bold , boolean addBreak) {
run.setFontFamily(fontFamily);
run.setFontSize(fontSize);
run.setColor(colorRGB);
run.setText(text);
run.setBold(bold);
if (addBreak) run.addBreak();
}
}
And this is what I've found and tried until now:
@RunWith(MockitoJUnitRunner.class)
public class ProffesionalSumaryServiceTest {
private static final String UID = "uid";
private static final int SKILL_SCORE = 3;
@InjectMocks
ProffesionalSumaryService proffesionalSumaryService;
ExportProfileDTO exportProfileDTO;
XWPFDocument mockDocument;
XWPFTable mockTable;
XWPFTableRow mockRow;
XWPFParagraph mockParagraph;
XWPFTableCell mockCell;
XWPFRun mockRun;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
exportProfileDTO = makeExportProfileDto();
mockDocument = mock(XWPFDocument.class);
mockTable = mock(XWPFTable.class, Mockito.RETURNS_DEEP_STUBS);
mockRow = mock(XWPFTableRow.class);
mockParagraph = mock(XWPFParagraph.class);
mockCell = mock(XWPFTableCell.class);
mockRun = mock(XWPFRun.class);
}
@Test
public void populateDocumentWithProfileSkills() {
CTBorder mockCTBorder = mock(CTBorder.class);
CTTblWidth mockCTTblWidth = mock(CTTblWidth.class);
when(mockDocument.createTable()).thenReturn(mockTable);
when(mockTable.getCTTbl().getTblPr().getTblBorders().getBottom()).thenReturn(mockCTBorder);
when(mockTable.getCTTbl().getTblPr().getTblBorders().getTop()).thenReturn(mockCTBorder);
when(mockTable.getCTTbl().getTblPr().getTblBorders().getLeft()).thenReturn(mockCTBorder);
when(mockTable.getCTTbl().getTblPr().getTblBorders().getRight()).thenReturn(mockCTBorder);
doNothing().when(mockCTBorder).setColor(anyString());
when(mockTable.getCTTbl().getTblPr().getTblW()).thenReturn(mockCTTblWidth);
doNothing().when(mockCTTblWidth).setType(Mockito.any());
doNothing().when(mockCTTblWidth).setW(Mockito.any());
when(mockDocument.createParagraph()).thenReturn(mockParagraph);
when(mockParagraph.createRun()).thenReturn(mockRun);
when(mockTable.getRow(anyInt())).thenReturn(mockRow);
when(mockRow.getCell(anyInt())).thenReturn(mockCell);
when(mockCell.addParagraph()).thenReturn(mockParagraph);
when(mockRow.createCell()).thenReturn(mockCell);
proffesionalSumaryService.populateDocumentWithProfileSkills(mockDocument,exportProfileDTO);
}
}
Do you know a better way of testing this class? I would appreciate any help.
回答1:
Your code is dominated by interactions with libraries. It contains only few computational parts. Moreover, the code creates a document that is meant to have a certain visual appearance.
It may make sense to extract the computational parts into separate methods and test these via unit-testing, but even that could be overkill here. The interactions, however, are better tested with integration-testing (that is, not with isolation using mocks). And, certainly, whether the result has the intended visual appearance needs to be analysed by looking at the resulting documents.
来源:https://stackoverflow.com/questions/57604594/how-to-write-unit-test-for-class-that-writes-data-into-word-document-with-apache