如何模拟属于JPA库的方法

时间:2014-04-07 16:08:36

标签: java jpa junit mockito

我想模拟以下方法对Xml进行JUnit测试:

void toXml(Object obj){
            ByteArrayOutputStream out = null;
            try{
                JAXBContext ctx = getContext(obj.getClass());
                Marshaller marshaller = ctx.createMarshaller();
                marshaller.setProperty(Marshaller.JAXB_FRAGMENT, true);
                marshaller.setAttachmentMarshaller(new AttachmentMarshallerImpl());
                out = new ByteArrayOutputStream();
                marshaller.marshal( obj, out );
            }catch( JAXBException e ){
                throw new RuntimeException("Problem in parsing", e);
            }
        }

我尝试了以下内容:

@Test
public void testToXml() throws Exception {

    ByteArrayOutputStream out = new ByteArrayOutputStream();
    SystemPointDto systemPointDto = new SystemPointDto();
    verify((marshaller), atLeast(1)).marshal(systemPointDto, out);
}

但是,当我运行测试时,我得到一个NullPointerException。我是测试的新手,可能答案非常简单。你能建议吗?提前谢谢。

编辑:

评论中提到的模拟代码是:

@Mock
AttachmentMarshallerImpl attachmentMarshaller;

@InjectMocks
Marshaller marshaller;

这是堆栈跟踪:

initMocks(TestingIfTheMarshalGetsCalledWithoutExceptionTest.java:34)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:24)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:160)
    at 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
Caused by: org.mockito.exceptions.base.MockitoException: the type 'Marshaller' is an interface.
    ... 32 more

1 个答案:

答案 0 :(得分:0)

在您的方法中,您从Marshaller获得JAXBContext。要使用模拟Marshaller,您需要一个JAXBContext,在调用createMarshaller时返回模拟。

假设下列课程正在测试中:

public class XmlMarshaller {
  private JAXBContextFactory contextFactory;

  public XmlMarshaller(JAXBContextFactory contextFactory) {
    this.contextFactory = contextFactory;
  }

  private JAXBContext getContext(Class<?> type) {
    return contextFactory.get(type);
  }

  public void toXml(Object obj){
    // ... your code
  }
}

您的测试设置需要如下所示:

public class XmlMarshallerTest {
  @Mock
  JAXBContext ctx;

  @Mock
  Marshaller marshaller;

  @Mock
  JAXBContextFactory factory;

  @InjectMocks
  XmlMarshaller classUnderTest;

  @Before
  public void setup() {
    MockitoAnnotations.initMocks(this); // creates mocks and injects the as needed into the classUnderTest

    when(ctx.createMarshaller()).thenReturn(marshaller);
  }

  @Test
  public void toXmlCallsJAXBMarshaller() {
    when(factory.get(SystemPointDto.class)).thenReturn(ctx);
    SystemPointDto systemPointDto = new SystemPointDto();

    classUnderTest.toXml(systemPointDto);

    verify(marshaller).marshal(eq(systemPointDto), any(ByteArrayOutputStream.class));
  }
}