【问题标题】:easymock how to mock / set public final variableeasymock 如何模拟/设置公共最终变量
【发布时间】:2014-01-05 17:56:02
【问题描述】:

我有一个类跟随类来测试模拟对象。

public class FordFulkerson {

FlowNetwork network;
Search searchMethod;    

public FordFulkerson (FlowNetwork network, Search method) {
    this.network = network;
    this.searchMethod = method;
}

public boolean compute () {
    boolean augmented = false;
    while (searchMethod.findAugmentingPath(network.vertices)) {
        processPath(network.vertices);
        augmented = true;
    }
    return augmented;
}

protected void processPath(VertexInfo []vertices) {
    int v = network.sinkIndex;

    // Determine the amount. Goal is to find the smallest 
    int delta = Integer.MAX_VALUE;
    while (v != network.sourceIndex) {
        int u = vertices[v].previous;

        // Over a forward edge, 
        int flow;
        if (vertices[v].forward) {
            flow = network.edge(u, v).capacity - network.edge(u, v).flow;
        } else {
            flow = network.edge(v, u).flow;
        }

        if (flow < delta) { delta = flow; }

        v = u;  // follow reverse path to source
    }

    // push minimal increment over the path
    v = network.sinkIndex;
    while (v != network.sourceIndex) {
        int u = vertices[v].previous;

        if (vertices[v].forward) {
            network.edge(u, v).flow += delta;
        } else {
            network.edge(v, u).flow -= delta;
        }

        v = u;  // follow reverse path to source
    }

    Arrays.fill(network.vertices, null);   // reset for next iteration.
}
}

我的测试:

public class FordFulkersonMockTest {
private FordFulkerson classUnderTest;
private FlowNetwork mockNetwork;
private Search mockSearch;

@Before
public void setUp() {
    mockNetwork = createMock(FlowNetwork.class);
    mockSearch = createMock(Search.class);
    classUnderTest = new FordFulkerson(mockNetwork, mockSearch );

}

@Test
public void test01() {
    expect(mockSearch.findAugmentingPath(null)).andReturn(false);

    replay(mockSearch);
    boolean res = classUnderTest.compute();
    assertEquals(false, res);
    verify(mockSearch);
}


@Test
public void test02() {
    expect(mockSearch.findAugmentingPath(null)).andReturn(true);
    try{
        Field f = mockNetwork.getClass().getDeclaredField("sinkIndex");
        f.setAccessible(true);
        f.set(mockNetwork, 0);
        f = mockNetwork.getClass().getDeclaredField("sourceIndex");
        f.setAccessible(true);
        f.set(mockNetwork, 0);
    }catch(Exception e)
    {
        fail(e.getMessage());
    }
    replay(mockNetwork);
    replay(mockSearch);
    boolean res = classUnderTest.compute();
    assertEquals(true, res);
    verify(mockSearch);
}

}

Test01 工作正常,但在 Test02 中我有问题。 在 Test02 方法中需要调用 processPath。它使用 mockNetwork 公共最终变量。我不知道在哪里设置它们。它导致空异常。在上面的代码中,我尝试更改此字段的可访问性并设置它们,但现在出现消息“sinkIndex”错误。

如何在 mockNetwork 中模拟 public final 变量? 我正在使用 Easymock。

【问题讨论】:

    标签: java unit-testing testing junit easymock


    【解决方案1】:

    您说您修改了FlowNetwork 的源代码,因此您可以执行以下操作,这将导致更健壮的设计和更容易测试:

    1. 封装这两个变量(即private int sinkIndexint getSinkIndex()
    2. expect(mockNetwork.getSinkIndex()).andReturn(0).anyTimes();

    猜测:mockNetwork.getClass() 正在返回一个没有状态(即没有字段)的 cglib EasyMock 代理,您可以在调试器中检查它。因此getDeclaredField() 正在返回null

    如果你真的想使用publics,你可以试试FlowNetwork.class.getDeclaredField

    【讨论】:

    • 不,我无法更改来源。那就是问题所在。我试图在 Test02 中更改它们的可访问性。
    • 啊,我明白了,你的意思是setAccessible,你试过我最后的编辑了吗?您也可以尝试不模拟网络,然后f.set 必须工作。
    • 我需要模拟网络,它的抽象。我试过你的最后一次编辑。现在我在 Arrays.fill(network.vertices, null); 处有空指针异常; (与不改变变量相同)
    • 好的,我已经处理好了。我还需要设置与这两个变量相同的顶点。谢谢
    • 是的,从createMock 返回的任何对象的每个字段都是null(或默认原语)。
    猜你喜欢
    • 2012-03-30
    • 2013-10-03
    • 1970-01-01
    • 2010-12-31
    • 1970-01-01
    • 2018-12-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多