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

发布于 2024-12-03 10:38:24 字数 935 浏览 2 评论 0原文

下面是我很难弄清楚如何使用 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;
}

Below is a method that I'm having a hard time figuring out how to test using JUnit.
This method is difficult to test because it depends on the results of other methods (e.g. getClosestDcoumentCode).

Based on my reading of JUnit, this suggests I should refactor the method. But how? And if refactoring is not necessary, how do you test a method that depends on other methods?

Thank you,

Elliott

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;
}

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

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

发布评论

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

评论(4

海夕 2024-12-10 10:38:24

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

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

一般来说,您可能需要

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

Well, first of all, I wonder if the method really needs to be static, and what that class is doing. It looks like it might be a GOD class, or at the very least it's violating the single responsibility principle. What does getClosestCode do? If it was a class, you could inject it with a stub in your tests into the test class.

EasyMock will let you mock the method response, but I'm not sure how you mock static methods.

In general, you probably need to

  1. Extract long functions into classes
  2. Make functionality non-static
  3. Maintain the single responsibility principal
为你鎻心 2024-12-10 10:38:24

在我看来,getClosestCodegetClosestDocumentCodefindPrincipal 方法属于不同的职责集。因此,您首先需要将它们分为两个不同的类。为每个要实现的类创建一个接口。然后,实现 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;
    }
}

现在应该很容易创建另一个实现 CodeFinder 接口的类,手动或使用模拟框架。然后,您可以控制每次调用 getClosestCodegetClosestDocumentCode 的结果,并确保使用您期望调用的参数来调用每个方法。

It sounds to me like getClosestCode and getClosestDocumentCode belong to a different set of responsibilities than the findPrincipal method. So you'll want to begin by separating these into two different classes. Create an interface for each class to implement. The class that implements the findPrincipal method can then rely on the other interface as a constructor argument, like this:

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;
    }
}

Now it should be easy to create another class the implements the CodeFinder interface, either manually or using a Mocking framework. You can then control the results of each call to getClosestCode and getClosestDocumentCode, and ensure that each of these methods gets called with exactly the arguments you expect it to be called with.

场罚期间 2024-12-10 10:38:24

我没有深入阅读该方法。但如果需要测试私有方法,则表明您的设计存在问题。至少Kent Beck 是这么认为的

I don't read the method deeply. But if a private method needs to test, it indicates something wrong with your design. At least Kent Beck thinks so.

絕版丫頭 2024-12-10 10:38:24

JUnit Second Edition 上有一个关于存根调用的章节,我建议您看一下,如果您认为您现有的代码未按照测试驱动开发标准编写。

There is a chapter on stub calls on JUnit Second Edition, i recommend you have a look at that if you think your existing codes are not written to test-driven development standards.

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