2

我有这个抽象类:

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 和这个特殊案例的问题。

4

2 回答 2

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 解封装的最佳方式,可以在不牺牲可见性的情况下测试很多东西。我知道这不能回答直接的问题,但我觉得你应该从中得到一些东西。随意投反对票并批评我社区。

于 2013-02-21T20:10:05.560 回答
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());
    }
}

希望能帮助到你。

于 2013-02-26T17:31:05.677 回答