【问题标题】:Powermockito doNothing for method with argumentsPowermockito doNothing 用于带参数的方法
【发布时间】:2014-04-10 07:10:58
【问题描述】:

我用 Java 开发了一个应用程序,我正在尝试使用 Powermockito 创建单元测试(我应该补充一点,我是单元测试的新手)。

我有一个名为 Resource 的类,它有一个名为 readResources 的静态方法:

public static void readResources(ResourcesElement resourcesElement);

ResourcesElement 也是我编写的。 在测试中,我想创建自己的Resource,所以我希望上面的方法什么都不做。 我尝试使用此代码:

    PowerMockito.spy(Resource.class);
    PowerMockito.doNothing().when(Resource.class, "readResources", Matchers.any(ResourcesElement.class));

单元测试抛出异常:

org.mockito.exceptions.misusing.UnfinishedStubbingException: 此处检测到未完成的存根: -> 在 org.powermock.api.mockito.internal.PowerMockitoCore.doAnswer(PowerMockitoCore.java:36)

Powermockito 还建议我应该在 when 之后使用 thenReturn 或 thenThrow,但似乎方法 'when' 在 doNothing 之后调用时返回 void(这是合乎逻辑的)。 如果我尝试:

PowerMockito.when(Resource.class, "readResources", Matchers.any(ResourcesElement.class)).....

doNothing 不是在 when 之后的选项。

我设法使没有参数的方法什么都不做,使用该方法的 2 参数版本。例如:

PowerMockito.doNothing().when(Moduler.class, "startProcessing");

这行得通(startProcessing 不接受任何参数)。

但是我怎样才能使带有参数的方法对 Powermockito 不做任何事情呢?

【问题讨论】:

    标签: java unit-testing powermock


    【解决方案1】:

    您可以在下面找到一个功能齐全的示例。由于您没有发布完整的示例,我只能假设您没有使用 @RunWith@PrepareForTest 注释测试类,因为其余部分看起来都很好。

    @RunWith(PowerMockRunner.class)
    @PrepareForTest({Resource.class})
    public class MockingTest{
    
        @Test
        public void shouldMockVoidStaticMethod() throws Exception {
            PowerMockito.spy(Resource.class);
            PowerMockito.doNothing().when(Resource.class, "readResources", Mockito.any(String.class));
    
            //no exception heeeeere!
            Resource.readResources("whatever");
    
            PowerMockito.verifyStatic();
            Resource.readResources("whatever");
        }
    
    }
    
    class Resource {
        public static void readResources(String someArgument) {
            throw new UnsupportedOperationException("meh!");
        }
    }
    

    【讨论】:

    • 谢谢,就是这样,我忘了用@PrepareForTest 进行注释(我的另一个示例正在工作,因为我记得在那里进行注释)。
    • 没问题,发生在我身上几次,我花了几个小时试图弄清楚
    • @Anakin001 : 如果在这种情况下 "readResources" 方法是私有且非静态的怎么办?
    • @NIKHILCHAURASIA 非常相似。你可以看到一个完整的例子here。您尝试了什么,遇到了什么问题?
    • PowerMockito.doNothing()... 这一行在模拟方法时也会调用 readResources 方法。有谁知道如何阻止它?
    【解决方案2】:

    为什么要经历这么多麻烦,只是为了让你的方法什么都不做。只需调用 PowerMockito.mockStatic(Resource.class) 即可将类中的所有静态方法替换为默认存根,这基本上意味着它们什么都不做。

    除非您确实想更改方法的行为以实际执行某些操作,否则只需调用 PowerMockito.mockStatic(Resource.class) 就足够了。当然,这也意味着类中的所有静态方法都是存根的,您需要考虑这一点。

    【讨论】:

      【解决方案3】:

      如果doNothing() 不起作用,您可以使用PowerMockito.doAnswer() 稍微破解一下。这可以让您模拟应该做某事的 void 方法,例如设置值等。如果 doNothing() 不起作用,使用空白 doAnswer() 应该可以正常工作。

      例子:

      PowerMockito.doAnswer(new org.mockito.stubbing.Answer<Object>() {
          @Override
          public Object answer(InvocationOnMock invocation) throws Throwable {
              return null; //does nothing
          }
      }).when(mockObject).methodYouWantToDoNothing(args);
      

      【讨论】:

      • 它可以工作,谢谢,但问题是我忘记使用 @PrepareForTest 进行注释,就像 Grove 建议的那样。不过,很好的答案,我会记住它以备将来使用(我不知道 doAnswer)。
      【解决方案4】:

      也许我无法理解您的问题,但我认为有必要指定必须做什么 该方法,所以如果你不指定 thenReturn 或 thenThrow 或任何 powerMockito 不知道在阅读你的真实代码时必须做什么,例如:

      真实代码:

                  IPager pag;
              IPagerData<List<IDeute>> dpag;
              pag = new PagerImpl();
              pag.setFiles(nombrefilesPaginador);
              pag.setInici(1);
              dpag = gptService.obtenirDeutes(idSubjecte, idEns, tipusDeute, periode, pag);
      

      通过 mockito 测试真实代码:

              IPager pag = new PagerImpl();
              pag.setInici(1);
              pag.setFiles(0);
              when(serveiGpt.obtenirDeutes(eq(331225L),
               eq(IConstantsIdentificadors.ID_ENS_BASE), 
               Matchers.any(ETipusDeute.class),
               Matchers.any(EPeriodeDeute.class), 
               eq(pag)))
              .thenThrow(new NullPointerException(" Null!"));
      

      如果没有指定返回,我的测试将失败。 希望对你有帮助。

      【讨论】:

      • 感谢您的回答。我不能返回任何东西,因为我的方法返回 void。另外,我不想抛出异常。我只是想让这个方法什么都不做。
      【解决方案5】:

      我尝试了 doNothing 的不同变体,但除了以下解决方案之外没有任何效果。

      @Before
      public void setUp(){
          obj = new ClassObj (parameters);
          //parameters should also include the class obj for which void method is available
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多