将 jmockit 期望与匹配器和原始类型结合使用

发布于 2024-07-04 10:56:13 字数 1229 浏览 9 评论 0原文

我正在使用 jmockit 进行单元测试(使用 TestNG),并且在使用 Expectations 类来模拟使用原始类型(布尔值)作为参数的方法(使用匹配器)时遇到问题。 这是一些说明问题的示例代码。

/******************************************************/
import static org.hamcrest.Matchers.is;

import mockit.Expectations;

import org.testng.annotations.Test;

public class PrimitiveMatcherTest {
  private MyClass obj;

  @Test
  public void testPrimitiveMatcher() {
    new Expectations(true) {
      MyClass c;
      {
        obj = c;
        invokeReturning(c.getFoo(with(is(false))), "bas");
      }
    };

    assert "bas".equals(obj.getFoo(false));

    Expectations.assertSatisfied();
  }

  public static class MyClass {
    public String getFoo(boolean arg) {
      if (arg) {
        return "foo";
      } else {
        return "bar";
      }
    }
  }
}
/******************************************************/

包含调用 invokeReturning(...) 的行抛出 NullPointerException。

如果我更改此调用以不使用匹配器,如下所示:

invokeReturning(c.getFoo(false), "bas");

它工作得很好。 这对我来说没有好处,因为在我的真实代码中,我实际上是在模拟多参数方法,并且我需要在另一个参数上使用匹配器。 在这种情况下,Expectations 类要求所有参数都使用匹配器。

我很确定这是一个错误,或者也许无法将匹配器与原始类型一起使用(这会让我感到难过)。 有没有人遇到过这个问题,并且知道如何解决它?

I'm using jmockit for unit testing (with TestNG), and I'm having trouble using the Expectations class to mock out a method that takes a primitive type (boolean) as a parameter, using a matcher. Here's some sample code that illustrates the problem.

/******************************************************/
import static org.hamcrest.Matchers.is;

import mockit.Expectations;

import org.testng.annotations.Test;

public class PrimitiveMatcherTest {
  private MyClass obj;

  @Test
  public void testPrimitiveMatcher() {
    new Expectations(true) {
      MyClass c;
      {
        obj = c;
        invokeReturning(c.getFoo(with(is(false))), "bas");
      }
    };

    assert "bas".equals(obj.getFoo(false));

    Expectations.assertSatisfied();
  }

  public static class MyClass {
    public String getFoo(boolean arg) {
      if (arg) {
        return "foo";
      } else {
        return "bar";
      }
    }
  }
}
/******************************************************/

The line containing the call to invokeReturning(...) throws a NullPointerException.

If I change this call to not use a matcher, as in:

invokeReturning(c.getFoo(false), "bas");

it works just fine. This is no good for me, because in my real code I'm actually mocking a multi-parameter method and I need to use a matcher on another argument. In this case, the Expectations class requires that all arguments use a matcher.

I'm pretty sure this is a bug, or perhaps it's not possible to use Matchers with primitive types (that would make me sad). Has anyone encountered this issue, and know how to get around it?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

无所谓啦 2024-07-11 10:56:14

问题是期望使用的组合以及匹配器不支持原始类型。

Matchers 代码依赖于 Generic,它基本上不支持原始类型。 通常Matchers的使用更多是为了匹配值; 使用 Java 5 中的自动装箱/拆箱功能,这通常不是问题。

但是 JMockit 的 Expectation 并不使用它来匹配值,而是使用它进行某种解析来确定方法调用签名类型..在这种情况下,匹配器将导致布尔类型,而您的方法是原始类型..所以它失败正确地嘲笑它。

很抱歉,我无法告诉您任何解决方法。 也许其他人可以帮忙。

the issue is the combination of Expectation usage and that Matchers does not support primitive type.

The Matchers code rely on Generic which basically does not support primitive type. Typically the usage of Matchers is more for matching value; with the auto-boxing/unboxing feater in Java 5, this is usually not a problem.

But JMockit's Expectation is not using it for matching value, it uses it for some kind of parsing to determine the method call signature type..which in this case the Matchers will resulted in Boolean type while your method is primitive type..so it fails to mock it properly.

I'm sorry that I can not tell you any workaround for this. Maybe somebody else can help.

南七夏 2024-07-11 10:56:14

我更改了 JMockit(版本 0.982),以便“with(is(false))”和其他类似的变体现在按预期工作(它不再返回 null,而是返回内部匹配器内的实际参数值)。

I changed JMockit (release 0.982) so that "with(is(false))" and other similar variations now work as expected (it no longer returns null, but the actual argument value inside the inner matcher).

梦里兽 2024-07-11 10:56:13

所以问题似乎出在 Expectations.with() 上:

   protected final <T> T with(Matcher<T> argumentMatcher)
   {
      argMatchers.add(argumentMatcher);

      TypeVariable<?> typeVariable = argumentMatcher.getClass().getTypeParameters()[0];

      return (T) Utilities.defaultValueForType(typeVariable.getClass());
   }

对 typeVariable.getClass() 的调用没有达到作者预期的效果,并且对 Utilities.defaultValueFor 类型的调用返回 null。 原始布尔值的去自动装箱是 NPE 的来源。

我通过将 invokeReturning(...) 调用更改为:

invokeReturning(withEqual(false)), "bas");

我不再在这里使用匹配器来修复它,但它足以满足我的需要。

So the problem appears to be in Expectations.with():

   protected final <T> T with(Matcher<T> argumentMatcher)
   {
      argMatchers.add(argumentMatcher);

      TypeVariable<?> typeVariable = argumentMatcher.getClass().getTypeParameters()[0];

      return (T) Utilities.defaultValueForType(typeVariable.getClass());
   }

The call to typeVariable.getClass() does not do what the author expects, and the call to Utilities.defaultValueFor type returns null. The de-autoboxing back the the primitive boolean value is where the NPE comes from.

I fixed it by changing the invokeReturning(...) call to:

invokeReturning(withEqual(false)), "bas");

I'm no longer using a matcher here, but it's good enough for what I need.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文