JMockit 麻烦(刚刚开始)

发布于 2024-09-17 21:57:32 字数 1611 浏览 8 评论 0原文

所以我有一个有点复杂的问题,我将用类似的例子来描述它,而不是复制大量的代码。问题在于我真的不知道如何很好地使用 JMockit,我敢说正确。

我有一个接口:

public interface IRsrcResolver {
 RsrcSet getForQuery(Query, RsrcContext, int);
}

它有一个真正的实现 - 它有点紧张。所以我制作了一个仅返回 null 的模拟版本。然后我想设置一个[非严格]期望,它将返回正确的值。它将测试更改为测试。

在代码中:

public class MockRsrcResolver implements IRsrcResolver { 
  RsrcSet getForQuery(Query, RsrcContext, int) { return null; } 
}

在 Test 类中我实现了它,然后想要设置期望(StateEngine 使用 RsrcResolver)

    public class StateEngineTest {
      @Mocked
      public IRsrcResolver rsrcResolver;
      @Mocked
      public RsrcSet rsrcSet;

      @Mocked
      private StateEngine stateEngine;


      public void setUp () throws Exception {
        stateEngine = new StateEngine ();
        rsrcResolver = new MockRsrcResolver ();
        rsrcSet = new RsrcSet ();

        new NonStrictExpectations () {
          {
            rsrcResolver.getForQuery((Query) any, (RsrcContext)any, anyInt);
            result = rsrcSet;
          }
        }
      }


    @Test
    public void testSetState () {
      /*... does something that calls getForQuery (...) on an IRsrcResolver ...*/
      stateTest.doSomething ();
      /* ... assert assert assert ... */
    }  
  }

在 doSomething 中,有类似这样的内容:

  IRsrcResolver m_rsrcResolver = new RsrcResolver ()
  RsrcSet m_rsrcSet = m_rsrcResolver.getQuery (query, rsrcCtx, 4);
  m_rsrcSet.doSomethingElse ();

m_rsrcSet 获取 null 值,调试显示它调用 null MockRsrcResolver,而不是使用期望... 我这样做是否不正确?感谢您的任何建议!

SO I have a kinda convoluted problem I will describe it with similar examples instead of copying TONS of code in. The problem comes in that I don't really know how to use JMockit well, dare I say properly.

I have an interface:

public interface IRsrcResolver {
 RsrcSet getForQuery(Query, RsrcContext, int);
}

There is a real implementation of it - it is kinda intense. So I made a mocked version that just returns null. I want to then set an [nonstrict]expectation that will return the proper values. It changes test to test.

In code:

public class MockRsrcResolver implements IRsrcResolver { 
  RsrcSet getForQuery(Query, RsrcContext, int) { return null; } 
}

in the Test class I implement it and then want set the expectations (StateEngine uses the RsrcResolver)

    public class StateEngineTest {
      @Mocked
      public IRsrcResolver rsrcResolver;
      @Mocked
      public RsrcSet rsrcSet;

      @Mocked
      private StateEngine stateEngine;


      public void setUp () throws Exception {
        stateEngine = new StateEngine ();
        rsrcResolver = new MockRsrcResolver ();
        rsrcSet = new RsrcSet ();

        new NonStrictExpectations () {
          {
            rsrcResolver.getForQuery((Query) any, (RsrcContext)any, anyInt);
            result = rsrcSet;
          }
        }
      }


    @Test
    public void testSetState () {
      /*... does something that calls getForQuery (...) on an IRsrcResolver ...*/
      stateTest.doSomething ();
      /* ... assert assert assert ... */
    }  
  }

In doSomething there is something like:

  IRsrcResolver m_rsrcResolver = new RsrcResolver ()
  RsrcSet m_rsrcSet = m_rsrcResolver.getQuery (query, rsrcCtx, 4);
  m_rsrcSet.doSomethingElse ();

m_rsrcSet gets a null value and the debug shows it calling into the null MockRsrcResolver, instead of using the expectation...
Am I incorrect in doing it this way? Thanks for any advice you may have!

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

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

发布评论

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

评论(1

人生百味 2024-09-24 21:57:32

JMockit 并不是很容易理解,因为当我们使用它时会发生很多神奇的事情,而且这可能非常不直观(尽管非常强大)。

在您的情况下,类 MockRsrcResolver 似乎没有用,因为您想模拟对 RsrcResolver 方法的调用(在测试代码中实例化)。

期望的模拟变量被滥用。不应给 rsrcResolverrsrcSetstateEngine 赋值。它们实际上是 JMockit 神奇生成的模拟实例的占位符。

解决方案 1

如果不必模拟 RsrcSet ,下面是我如何模拟此方法:

final RsrcSet queryResult = new RsrcSet();
// (insert initialization of queryResult here)

new NonStrictExpectations () {
  RsrcResolver rsrcResolver;
  {
    rsrcResolver.getForQuery((Query) any, (RsrcContext)any, anyInt);
    result = queryResult
  }
}

请注意,我将“模拟占位符”变量声明为期望的成员,而不是测试课。也许后者也有效,我不知道(有很多方法可以用 JMockit 达到相同的结果)。但重要的一点是我不会重新分配这些变量。

上述期望意味着:“拦截RsrcResolver#getForQuery方法的每次调用并返回queryResult实例”。
实际上,当使用非严格期望(我主要使用严格期望)时,我不确定确切的行为。也许这意味着:“拦截 RsrcResolver 的每个方法的调用,不执行任何操作并返回默认值。但是对于方法 RsrcResolver#getForQuery 的特殊情况,返回 queryResult 实例。”

解决方案 2

如果 RsrcSet#doSomethingElse 也必须被模拟,那么我将如何模拟这个方法:

new NonStrictExpectations () {
  RsrcResolver rsrcResolver;
  RsrcSet rsrcSet;
  {
    rsrcResolver.getForQuery((Query) any, (RsrcContext)any, anyInt);
    result = rsrcSet;
    rsrcSet.doSomethingElse();
  }
}

上述期望意味着:“拦截该方法的每个调用 RsrcResolver#getForQuery > 并返回一个模拟的 RsrcSet 实例,该模拟实例在调用时不会执行任何操作”。当然,如果doSomethingElse必须返回一个值,您可以使用result =指令。

JMockit is not really easy to understand, because there is a lot of magic happening when we use it, and this can be very unintuitive (though very powerful).

In your situation, it appears that the class MockRsrcResolver is useless, since you want to mock a call to a method of RsrcResolver (which is instanciated in the tested code).

There is a misuse of the expectation's mocked variables. rsrcResolver, rsrcSet and stateEngine should not be given a value. They are actually placeholders for the mocked instances that JMockit magically generates.

Solution 1

Here is how I would have mocked this method, if RsrcSet doesn't have to be mocked :

final RsrcSet queryResult = new RsrcSet();
// (insert initialization of queryResult here)

new NonStrictExpectations () {
  RsrcResolver rsrcResolver;
  {
    rsrcResolver.getForQuery((Query) any, (RsrcContext)any, anyInt);
    result = queryResult
  }
}

Note that I declare the "mock placeholder" variables as member of the expectation, not as member of the test class. Maybe the latter works too, I don't know (there are many ways to achieve the same result with JMockit). But the important point is that I don't reassign those variables.

The above expectation means : "intercept every calls of the method RsrcResolver#getForQuery and return the queryResult instance instead".
Actually I'm not sure about the precise behavior, when using non-strict expectations (I mainly use strict ones). Maybe it means : "intercept calls of every methods of RsrcResolver, doing nothing and returning default values. But for the special case of method RsrcResolver#getForQuery, return the queryResult instance."

Solution 2

Here is how I would have mocked this method, if RsrcSet#doSomethingElse has to be mocked too :

new NonStrictExpectations () {
  RsrcResolver rsrcResolver;
  RsrcSet rsrcSet;
  {
    rsrcResolver.getForQuery((Query) any, (RsrcContext)any, anyInt);
    result = rsrcSet;
    rsrcSet.doSomethingElse();
  }
}

The above expectation means : "intercept every calls of the method RsrcResolver#getForQuery and return a mocked RsrcSet instance instead. This mocked instance will do nothing when called". Of course, if doSomethingElse has to return a value, you can use a result = instruction.

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