【问题标题】:Junit for a method containing getClassLoader().getResource()包含 getClassLoader().getResource() 的方法的 Junit
【发布时间】:2018-11-08 13:04:34
【问题描述】:

我的代码中有以下服务类。

public class MyServiceImpl {

public List<Group> getGroups() throws JAXBException {
List<Group> viewModel = new ArrayList<Group>();
File file = new File(MyServiceImpl.class.getClassLoader().getResource("filename").getPath());
.....
....
 }
}

我正在尝试为getGroups() 方法编写一个Junit,但我被困在创建新文件的那一行。我尝试使用 EasyMock 和 Mockito,但无法正常工作。

EasyMock.expect(MyServiceImpl.class.getClassLoader().getResource("filename").getPath()).andReturn("path");

运行测试时我得到以下信息。

java.lang.NullPointerException
at com.mysite.services.content.MyServiceImplTest.testGetGroups(MyServiceImplTest.java:42)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:31)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:44)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:180)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:41)
at org.junit.runners.ParentRunner$1.evaluate(ParentRunner.java:173)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:31)
at org.junit.runners.ParentRunner.run(ParentRunner.java:220)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)

编辑

添加测试类。

public class MyServiceImplTest {

private MyServiceImpl service;

@Before
public void setup() {
    service = new MyServiceImpl();
}

@Test
public void testGetGroups() throws Exception {
    EasyMock.expect(MyServiceImpl.class.getClassLoader().getResource("filename").getPath()).andReturn("path");

    service.getGroups();
}

感谢任何帮助。谢谢。

【问题讨论】:

    标签: java unit-testing junit mockito easymock


    【解决方案1】:

    我能够通过创建一个测试文件filename 并将其放在src/test/resource 文件夹中来解决上述问题,并且当我运行测试时它通过了。

    【讨论】:

      【解决方案2】:

      在调用 mocked 方法之前,您是否以 mock 作为参数调用 EasyMocks 的 replay 方法?如果不是,这可能就是您收到空指针异常的原因。

      【讨论】:

      • 添加重播和验证方法后再次尝试,但没有成功。编辑问题以添加测试类。
      【解决方案3】:

      添加测试类后,我看到了问题。

      试试这个:

      public class MyServiceImplTest {
          private MyServiceImpl service;
      
          @Before
           public void setup() {
                service = EasyMock.createMock(MyServiceImpl.class);
           }
      
           @Test
            public void testGetGroups() throws Exception {
      
            EasyMock.expect(MyServiceImpl.getClass.getClassLoader()
            .getResource("filename")
            .getPath())
            .andReturn("path");
      
             EasyMock.replay(service);
             //Do something with Mock
             EasyMock.verify(service);
      
       }
      

      如果您想调用 service.getGroups(),您需要模拟该方法调用或使用部分模拟。看这里并搜索部分模拟:EasyMock Guide

      【讨论】:

      • 测试在 EasyMock.expect() 行失败。创建类的模拟不起作用。
      • 在进一步检查和喝咖啡后,我注意到您将方法调用链接在一起,并且这些方法返回未被模拟的其他对象。由于模拟没有返回这些对象(如果不清楚,请阅读有关模拟的更多信息),因此您只是返回 null 而不是您所期望的。您需要创建一个模拟类加载器并让模拟 serviceimpl.class 返回该模拟等等。
      【解决方案4】:

      这里的模拟在哪里?请阅读 EasyMock 文档,因为您还不了解模拟的工作原理。

      您希望MyServiceImpl.class.getClassLoader().getResource("filename").getPath() 返回一个特定值。这实际上是不可能做到的。这意味着模拟MyServiceImpl.class(不可能,至少很容易)比模拟ClassLoaderURI

      但是这样做是没有意义的。真正的问题是:为什么要嘲笑它?这应该在您的测试环境中有一个已知且明确的答案。只需在测试中使用它即可。

      如果出于某种奇怪的原因,你真的想改变这个答案,你应该重构你的代码和一些方法,比如

      protected File getFileToMe() {
          return new File(getClass().getResource("/filename").getPath());
      }
      

      然后您可以使用匿名内部类或部分模拟来测试是否覆盖该方法。

      【讨论】:

        猜你喜欢
        • 2011-04-17
        • 2010-10-12
        • 1970-01-01
        • 2013-01-22
        • 2017-08-12
        • 2015-04-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多