如何重构方法以使其更容易测试

Ell*_*ott 0 java testing junit refactoring

下面是一个方法,我很难弄清楚如何使用JUnit进行测试.
这种方法很难测试,因为它取决于其他方法的结果(例如getClosestDcoumentCode).

基于我对JUnit的阅读,这表明我应该重构该方法.但是怎么样?如果不需要重构,您如何测试依赖于其他方法的方法?

谢谢,

埃利奥特

private static String findPrincipal(List<DocumentKey> documentkeys_) {
    Hashtable<String, Integer> codecounts = new Hashtable<String, Integer>();
    for (DocumentKey document : documentkeys_) {
        int x = 0;
        String closestCode = getClosestDocumentCode(document.candidates);
        if (closestCode == null) continue;
        int thecount = 0;
        if (codecounts.containsKey(closestCode))
            thecount = codecounts.get(closestCode);
        if (document.hasKey)
            thecount += 2;
        else
            thecount++;
        codecounts.put(closestCode, new Integer(thecount));
        x++;

    }
    String closestCode = getClosestCode(codecounts);
    return closestCode;
}
Run Code Online (Sandbox Code Playgroud)

Ste*_*all 7

好吧,首先,我想知道该方法是否真的需要是静态的,以及该类正在做什么.看起来它可能是一个GOD类,或者至少它违反了单一责任原则.getClosestCode有什么作用?如果它是一个类,你可以在测试中将它与一个存根注入到测试类中.

EasyMock会让你模拟方法响应,但我不确定你如何模拟静态方法.

一般来说,你可能需要

  1. 将长函数提取到类中
  2. 使功能非静态
  3. 维护单一责任主体


Str*_*ior 5

听起来我喜欢getClosestCode并且getClosestDocumentCode属于与方法不同的责任findPrincipal.所以你要首先将它们分成两个不同的类.为每个要创建的类创建一个接口.然后,实现该findPrincipal方法的类可以依赖其他接口作为构造函数参数,如下所示:

public class PrincipalFinderImpl implements PrincipalFinder
{
    private CodeFinder codeFinder;
    public PrincipalFinderImpl(CodeFinder codeFinder) {
        this.codeFinder = codeFinder;
    }
    public String findPrincipal(List<DocumentKey> documentkeys_) {
        Hashtable<String, Integer> codecounts = new Hashtable<String, Integer>();
        for (DocumentKey document : documentkeys_) {
            int x = 0;
            String closestCode = codeFinder.getClosestDocumentCode(document.candidates);
            if (closestCode == null) continue;
            int thecount = 0;
            if (codecounts.containsKey(closestCode))
                thecount = codecounts.get(closestCode);
            if (document.hasKey)
                thecount += 2;
            else
                thecount++;
            codecounts.put(closestCode, new Integer(thecount));
            x++;

        }
        String closestCode = codeFinder.getClosestCode(codecounts);
        return closestCode;
    }
}
Run Code Online (Sandbox Code Playgroud)

现在,应该很容易创建另一个实现CodeFinder接口的类,手动或使用Mocking框架.然后,您可以控制每个呼叫的结果getClosestCodegetClosestDocumentCode,并确保每一种方法被调用与正是你希望它与被调用的参数.