【问题标题】:Method is not gettting mocked (Mockito.when().thenReturn()) and not returning specified mock value方法没有被模拟(Mockito.when().thenReturn())并且没有返回指定的模拟值
【发布时间】:2017-03-24 05:21:21
【问题描述】:

我正在为一个受保护的方法编写测试用例,该方法被调用

protected boolean printMultipleImages(int rows, int cols, IIOImage[] imgs,
                                      PrintMode mode, AutomaticCroppingOption crop,
                                      double reduction, int renderOption)

在这个方法中,一个数组变量被初始化,下面的代码展示了如何

RenderRequest request = this.formSlotsRenderRequest(rows, cols, imgs,mode, crop, reduction);
        // Create a Printer Properties Object...
        PrinterProperties prop = this.getAutoPrinterProperties();
        // Get the Appropriate Print Rendering Engine..
        MultiFilmPrintRenderer engine = this.getPrintRenderer();

        MultiFilmRenderRequest multiFilmRenderRequest = new MultiFilmRenderRequest(renderOption, request,new ChoppingPreferences());

        assert engine != null;

        RenderedImage[] rImageArr =engine.renderAcrossFilms(multiFilmRenderRequest, prop); //NPE here, rImageArr=null, though I mocked the method to return something.

在下面突出显示的行中,变量rImageArr 没有被初始化并且保持为空, 方法调用engine.renderAcrossFilms(multiFilmRenderRequest, prop); 给我null,即使我模拟它返回一些东西,并且控件进入方法内部并给出空指针异常,这不应该发生,因为我正在模拟它。这里使用的所有变量都是方法的局部变量。

RenderedImage[] rImageArr =engine.renderAcrossFilms(multiFilmRenderRequest, prop);

这就是我嘲笑engine.renderAcrossFilms(multiFilmRenderRequest, prop);方法的方式

@Test
    public void testPrintMultipleImages() throws Exception
    {
        //MultiFilmRenderRequest req=Mockito.mock(MultiFilmRenderRequest.class);
        MultiFilmPrintRenderer engine=Whitebox.getInternalState(autoPrintEndPoint, "_engine");//new JCPrintRenderEngine();//
        System.out.println(engine+"here");

        RenderedImage[] renderAcrossFilms=new RenderedImage[]{Mockito.mock(RenderedImage.class)};
        PrinterProperties prop=Mockito.mock(PrinterProperties.class);
        RenderRequest renderRequest=Mockito.mock(RenderRequest.class);
        AutomaticCroppingOption crop=Mockito.mock(AutomaticCroppingOption.class);
        PrintMode mode=Mockito.mock(PrintMode.class);
        IIOImage img=Mockito.mock(IIOImage.class);

        MultiFilmRenderRequest multiFilmRenderRequest = new MultiFilmRenderRequest(1, renderRequest,
                                     new ChoppingPreferences());

        PowerMockito.doNothing().when(autoPrintEndPoint,PowerMockito.method(AutoPrintEndPoint.class,"loadImage", IIOImage.class)).withArguments(img);
        PowerMockito.doReturn(renderRequest).when(autoPrintEndPoint,PowerMockito.method(AutoPrintEndPoint.class,"formSlotsRenderRequest", int.class, int.class, IIOImage[].class,PrintMode.class,AutomaticCroppingOption.class,double.class)).withArguments(2,2,new IIOImage[]{img},mode,crop,12.5);
        PowerMockito.doReturn(prop).when(autoPrintEndPoint,PowerMockito.method(AutoPrintEndPoint.class,"getAutoPrinterProperties")).withNoArguments();
              Mockito.when(engine.renderAcrossFilms(Mockito.any(MultiFilmRenderRequest.class),Mockito.any(PrinterProperties.class))).thenReturn(renderAcrossFilms);

        Method printMultipleImages=AutoPrintEndPoint.class.getDeclaredMethod("printMultipleImages", int.class,int.class,IIOImage[].class,PrintMode.class,AutomaticCroppingOption.class,double.class,int.class);
        printMultipleImages.setAccessible(true);
        printMultipleImages.invoke(autoPrintEndPoint,2,2,new IIOImage[]{img},mode,crop,12.5,1);

    }

我希望我的问题足够清楚,我希望你能帮助我

【问题讨论】:

  • 你是如何定义变量renderAcrossFilms的?
  • 另外,您是否尝试过使用 any() 匹配器作为参数?
  • @muzzlator RenderedImage[] renderAcrossFilms=new RenderedImage[]{Mockito.mock(RenderedImage.class)}; 我没有使用任何匹配器。
  • 我现在很困惑 Akhil,也许是一些调试语句来澄清你所看到的?你在哪里获得NPE?随意在您的帖子中添加更多代码
  • @muzzlator 我在上面发布的第二段代码的最后一行中突出显示了我获得 NPE 的行。

标签: java unit-testing exception junit mockito


【解决方案1】:

随着您提供更多详细信息,我将继续扩展此答案,但根据您的最新更新,您有:

MultiFilmPrintRenderer engine =
    Whitebox.getInternalState(autoPrintEndPoint, "_engine");
// ...
Mockito.when(engine.renderAcrossFilms(multiFilmRenderRequest, prop))
    .thenReturn(renderAcrossFilms);

那么这个 Whitebox.getInternalState 是否返回一个模拟对象?

【讨论】:

  • 它给了我null。我尝试模拟对象而不是做一个 getInternalState 但仍然模拟不起作用并给我 NPE
  • 为什么这些在你的问题的同一个代码块中?
  • 我现在已经添加了整个测试用例。希望我现在面临的问题会更清楚。
【解决方案2】:

在您要测试的方法中, 它创建了新实例

MultiFilmRenderRequest multiFilmRenderRequest = new MultiFilmRenderRequest(renderOption, request,new ChoppingPreferences());

这将用作模拟方法的参数。 但是您可能已经模拟了提供参数的方法,该参数不等于 printMultipleImages 方法传递给引擎的参数。

除此之外我可以看到 PrinterProperties prop=Mockito.mock(PrinterProperties.class);

但是这个模拟类没有被使用,所以目标测试方法可能再次发送一个不同的 PrinterProperties 对象。

你可以使用

engine.renderAcrossFilms(Mockito.any(MultiFilmRenderRequest.class),Mockito.any(PrinterProperties.class))

【讨论】:

  • 我在我的模拟中也传递了相同的参数,但它仍然抛出一个 NPE
  • 你是如何传递相同的参数的,因为第一个参数是在调用engine.renderAcrossFilms之前在方法中创建的,那么你是如何访问该值的。
  • 我调用构造函数的方式与在方法中调用构造函数的方式相同,并将其作为参数传递。我已经编辑了帖子并显示了我通过的参数。你可以看看。我仍然是这方面的业余爱好者,还在学习,所以请坦诚面对错误。
  • 所以这意味着你已经覆盖了 MultiFilmRenderRequest 中的 equal(Object) 方法?
  • 不,我只是试图使参数与被测方法中传递的参数相同。我也尝试过传递模拟对象,但即使那样模拟也不起作用。
【解决方案3】:

我在 engine 对象上创建了一个模拟对象,该对象用于调用我试图模拟的方法并执行了 setInternalState。

MultiFilmPrintRenderer engine = Mockito
                .mock(MultiFilmPrintRenderer.class);
Whitebox.setInternalState(autoPrintEndPoint, "_engine", engine);

这样设置了模拟对象。并且 NPE 已解决

【讨论】:

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