如何使用JMockit模拟具有泛型的继承方法

时间:2012-09-11 14:40:08

标签: jmockit

我有这个抽象类:

public abstract class Accessor<T extends Id, U extends Value>
{
   public U find(T id)
   {
        // let's say
        return getHelper().find(id);
   }
}

实施:

public FooAccessor extends Accessor<FooId,Foo>
{
    public Helper getHelper
    {
        // ...
        return helper;
    }
}

我想嘲笑对FooAccessor.find的调用。 这样:

@MockClass(realClass=FooAccessor.class)
static class MockedFooAccessor
{
    public Foo find (FooId id)
    {
        return new Foo("mocked!");
    }
}

将因此错误而失败:

java.lang.IllegalArgumentException: Matching real methods not found for the following mocks of MockedFooAccessor:
Foo find (FooId)

我理解为什么......但我不知道我怎么能做到这一点。

注意:是的,我可以模拟getHelper方法,得到我想要的东西;但这是一个关于JMockit和这个特殊案例的更多问题。

2 个答案:

答案 0 :(得分:2)

我找到的唯一方法是使用字段

@Test
public void testMyFooMethodThatCallsFooFind(){
MyChildFooClass childFooClass = new ChildFooClass();
String expectedFooValue = "FakeFooValue";
new NonStrictExpectations(){{
 setField(childFooClass, "fieldYouStoreYourFindResultIn", expectedFooValue);
}};

childFooClass.doSomethingThatCallsFind();

// if your method is protected or private you use Deencapsulation class 
// instead of calling it directly like above
Deencapsulation.invoke(childFooClass, "nameOfFindMethod", argsIfNeededForFind);
// then to get it back out since you used a field you use Deencapsulation again to pull out the field
String actualFoo = Deencapsulation.getField(childFooClass, "nameOfFieldToRunAssertionsAgainst");

assertEquals(expectedFooValue ,actualFoo);

}

childFooClass不需要被模拟,也不需要模拟父类。

如果不了解您的具体情况,这个策略是我利用jMockit去除封装的最佳方式,可以在不牺牲可见性的情况下测试很多东西。我知道这并没有回答直接的问题,但我觉得你应该从中得到一些东西。随意贬低和惩罚我的社区。

答案 1 :(得分:2)

老实说,我发现它与嘲弄常规课程没有任何不同。一种方法是告诉JMockit仅模拟find方法并使用Expectations块来提供替代实现。像这样:

abstract class Base<T, U> {
    public U find(T id) {
        return null;
    }
}

class Concrete extends Base<Integer, String> {
    public String work() {
        return find(1);
    }
}

@RunWith(JMockit.class)
public class TestClass {

    @Mocked(methods = "find")
    private Concrete concrete;

    @Test
    public void doTest() {

        new NonStrictExpectations() {{
            concrete.find((Integer) withNotNull());
            result = "Blah";
        }}

        assertEquals("Blah", concrete.work());
    }
}

希望它有所帮助。