2

I have written a class that writes data into a word document. Now I have to write mockito tests for my class. My problem is that I don't know how to mock getCTTbl().getTblPr().getTblBorders().getBottom().setColor() on a mock table.

this is part of the method I'm trying to write test for.

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);
...
}

What I've done so far is:

@Before
    public void setup() {
        MockitoAnnotations.initMocks(this);
        exportProfileDTO = makeExportProfileDto();
        mockDocument = mock(XWPFDocument.class);
        mockTable = mock(XWPFTable.class);
    }
    @Test
    public void populateDocumentWithProfileSkills(){

        when(mockDocument.createTable()).thenReturn(mockTable);

proffesionalSumaryService.populateDocumentWithProfileSkills(mockDocument,exportProfileDTO);

    }

If I say

CTTbl mockCTTbl = mock(CTTbl.class);

when(mockTable.getCTTbl()).thenReturn(mockCTTbl);

then I get the error

Mockito cannot mock this class: interface org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTbl.

Mockito can only mock non-private & non-final classes.
If you're not sure why you're getting this error, please report to the mailing list.


Java               : 1.8
JVM vendor name    : Private Build
JVM vendor version : 25.222-b10
JVM name           : OpenJDK 64-Bit Server VM
JVM version        : 1.8.0_222-8u222-b10-1ubuntu1~18.04.1-b10
JVM info           : mixed mode
OS name            : Linux
OS version         : 5.0.0-25-generic


Underlying exception : java.lang.IllegalArgumentException: Could not create type

    at com.model.profileDocument.ProffesionalSumaryServiceTest.populateDocumentWithProfileSkills(ProffesionalSumaryServiceTest.java:77)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.mockito.internal.runners.DefaultInternalRunner$1.run(DefaultInternalRunner.java:79)
    at org.mockito.internal.runners.DefaultInternalRunner.run(DefaultInternalRunner.java:85)
    at org.mockito.internal.runners.StrictRunner.run(StrictRunner.java:39)
    at org.mockito.junit.MockitoJUnitRunner.run(MockitoJUnitRunner.java:163)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
    at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
Caused by: java.lang.IllegalArgumentException: Could not create type
    at net.bytebuddy.TypeCache.findOrInsert(TypeCache.java:140)
    at net.bytebuddy.TypeCache$WithInlineExpunction.findOrInsert(TypeCache.java:346)
    at net.bytebuddy.TypeCache.findOrInsert(TypeCache.java:161)
    at net.bytebuddy.TypeCache$WithInlineExpunction.findOrInsert(TypeCache.java:355)
    at org.mockito.internal.creation.bytebuddy.TypeCachingBytecodeGenerator.mockClass(TypeCachingBytecodeGenerator.java:32)
    at org.mockito.internal.creation.bytebuddy.SubclassByteBuddyMockMaker.createMockType(SubclassByteBuddyMockMaker.java:71)
    at org.mockito.internal.creation.bytebuddy.SubclassByteBuddyMockMaker.createMock(SubclassByteBuddyMockMaker.java:42)
    at org.mockito.internal.creation.bytebuddy.ByteBuddyMockMaker.createMock(ByteBuddyMockMaker.java:25)
    at org.mockito.internal.util.MockUtil.createMock(MockUtil.java:35)
    at org.mockito.internal.MockitoCore.mock(MockitoCore.java:65)
    at org.mockito.Mockito.mock(Mockito.java:1855)
    at org.mockito.Mockito.mock(Mockito.java:1768)
    ... 28 more
Caused by: java.lang.NoClassDefFoundError: org/openxmlformats/schemas/wordprocessingml/x2006/main/CTPerm
    at java.lang.Class.getDeclaredMethods0(Native Method)
    at java.lang.Class.privateGetDeclaredMethods(Class.java:2701)
    at java.lang.Class.getDeclaredMethods(Class.java:1975)
    at net.bytebuddy.description.method.MethodList$ForLoadedMethods.<init>(MethodList.java:90)
    at net.bytebuddy.description.type.TypeDescription$ForLoadedType.getDeclaredMethods(TypeDescription.java:7326)
    at net.bytebuddy.description.type.TypeDescription$Generic$OfNonGenericType.getDeclaredMethods(TypeDescription.java:3380)
    at net.bytebuddy.dynamic.scaffold.MethodGraph$Compiler$Default.doAnalyze(MethodGraph.java:576)
    at net.bytebuddy.dynamic.scaffold.MethodGraph$Compiler$Default.analyze(MethodGraph.java:537)
    at net.bytebuddy.dynamic.scaffold.MethodGraph$Compiler$Default.doAnalyze(MethodGraph.java:573)
    at net.bytebuddy.dynamic.scaffold.MethodGraph$Compiler$Default.compile(MethodGraph.java:508)
    at net.bytebuddy.dynamic.scaffold.MethodGraph$Compiler$AbstractBase.compile(MethodGraph.java:408)
    at net.bytebuddy.dynamic.scaffold.MethodRegistry$Default.prepare(MethodRegistry.java:418)
    at net.bytebuddy.dynamic.scaffold.subclass.SubclassDynamicTypeBuilder.make(SubclassDynamicTypeBuilder.java:162)
    at net.bytebuddy.dynamic.scaffold.subclass.SubclassDynamicTypeBuilder.make(SubclassDynamicTypeBuilder.java:155)
    at net.bytebuddy.dynamic.DynamicType$Builder$AbstractBase.make(DynamicType.java:2639)
    at net.bytebuddy.dynamic.DynamicType$Builder$AbstractBase$Delegator.make(DynamicType.java:2741)
    at org.mockito.internal.creation.bytebuddy.SubclassBytecodeGenerator.mockClass(SubclassBytecodeGenerator.java:120)
    at org.mockito.internal.creation.bytebuddy.TypeCachingBytecodeGenerator$1.call(TypeCachingBytecodeGenerator.java:37)
    at org.mockito.internal.creation.bytebuddy.TypeCachingBytecodeGenerator$1.call(TypeCachingBytecodeGenerator.java:34)
    at net.bytebuddy.TypeCache.findOrInsert(TypeCache.java:138)
    ... 39 more
Caused by: java.lang.ClassNotFoundException: org.openxmlformats.schemas.wordprocessingml.x2006.main.CTPerm
    at java.net.URLClassLoader.findClass(URLClassLoader.java:382)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:349)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
    ... 59 more

I would appreciate any suggestions on how to do that or maybe a better aproach on how to test this class.

  • I can't reproduce that error. I imported `ooxml-schemas` version `1.4` and mockito (v3.0.0) did not complain about it. What versions are you using? – second Aug 21 '19 at 13:58
  • I am using poi-ooxml version 3.15 and mockito(2.15.0). I tried mockito 3.0.0 and I get 'Mockito cannot mock this class: XWPFDocument' – Elisabeta Alexa Aug 21 '19 at 14:11
  • Ok. With `poi-ooxml version 3.15` I also get an exception. However the underlying cause is a `ClassNotFound`, which indicates a missing dependency. Can you add your full stacktrace to the question? – second Aug 21 '19 at 14:37
  • @second I added. – Elisabeta Alexa Aug 22 '19 at 06:54

2 Answers2

0

I assume that you have to use Mockito.RETURNS_DEEP_STUBS option in below way in the setup method

 mockDocument = mock(XWPFDocument.class);
 mockTable = mock(XWPFTable.class, Mockito.RETURNS_DEEP_STUBS);

so the Mockito framework returns you a mock for each get calls, the get calls don't have to be static.

  • ok, but that doesn't solve my problem. Becuse 'This feature will not work when any return type of methods included in the chain cannot be mocked (for example: is a primitive or a final class). This is because of java type system.' My problem is that CTTbl.class, for some reason cannot be mocked, (either with Mockito.RETURNS_DEEP_STUBS or without). – Elisabeta Alexa Aug 22 '19 at 08:15
0

http://poi.apache.org/components/index.html

poi-ooxml requires poi-ooxml-schemas. This is a substantially smaller version of the ooxml-schemas jar (ooxml-schemas-1.4.jar for POI 4.0.0 or later, ooxml-schemas-1.3.jar for POI 3.14 or to POI 3.17, ooxml-schemas-1.1.jar for POI 3.7 up to POI 3.13, ooxml-schemas-1.0.jar for POI 3.5 and 3.6). The larger ooxml-schemas jar is normally only required for development. Similarly, the ooxml-security jar, which contains all of the classes relating to encryption and signing, is normally only required for development. A subset of its contents are in poi-ooxml-schemas. This JAR is ooxml-security-1.1.jar for POI 3.14 onwards and ooxml-security-1.0.jar prior to that.

Which basically says you will need to add the matching ooxml-schemas jar to your pom to have access to all related classes.

You might want to use a different scope as it says its only required for development, but you have to verify that for yourself.

<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>ooxml-schemas</artifactId>
    <version>1.3</version>
</dependency>
second
  • 4,069
  • 2
  • 9
  • 24
  • Glad to be of help. Feel free to ask a new question about `how to test` the method, the short snippet here doesn't really show much, but I am not convinced that it is really necessary to mock `XWPFDocument` in the first place. – second Aug 22 '19 at 09:12
  • I already did that. Feel free to check at [link](https://stackoverflow.com/questions/57604594/how-to-write-unit-test-for-class-that-writes-data-into-word-document-with-apache) . – Elisabeta Alexa Aug 22 '19 at 09:23