Designing classes to help Junit Testing

huangapple go评论59阅读模式
英文:

Designing classes to help Junit Testing

问题

以下是您提供的代码部分的翻译:

我将尝试通过伪代码来解释我在测试Spring Boot应用程序时遇到的代码质量或设计问题

public class ControllerClass {
    controllerMethod(@RequestParam(version) String version) {

        service.generateFile(version)

    }
}

public class ServiceClass {

    private map = new HashMap<> ();

    void generateFile(version) {
        String rVersion = fetchRversion(version);
        String json = makeApiCall(url + rVersion);
        build(map);
        generateData(json)

    }
    generateData(json) {
        // 使用 map
    }
}

上述的编码方式在测试 generateData 方法时会引发问题
因此如果我有 JSON 数据我将其传递给 generateData 函数
问题将在于 map 是在 generateFile 函数内构建的
所以这不会起作用要么我在 generateData 的测试函数中构建 map要么有一种方法可以创建带有 map 的 Service 类对象以便没有测试函数需要关心构建或实例化其他数据由于版本是在运行时传递的根据该版本构建 map是否适合在服务类中有一个单独的构建函数可以在其中设置所有所需的内容
还有其他方法可以解决这个问题吗

请注意,上述翻译是您提供的代码的翻译部分。如果您需要关于这段代码的更多解释或建议,请随时提出。

英文:

I will try to explain through pseudocode a code quality or design issue that I encountered while testing a spring boot application:

public class ControllerClass {
    controllerMethod(@RequestParam(version) String version) {

        service.generateFile(version)

    }
}

public class ServiceClass {

    private map = new HashMap<> ();

    void generateFile(version) {
        String rVersion = fetchRversion(version);
        String json = makeApiCall(url + rVersion);
        build(map);
        generateData(json)

    }
    generateData(json) {
        // uses map
    }
}

The above way of coding cause trouble when testing the generateData method.
So if I have the JSON, I pass it to the generateData function.
The trouble will be that map is built inside the generateFile function.
So it won't work. Either I built the map inside the test function for generateData or there could be some way of creating the Service class object with the map so that no testing function has to care about building or instantiating any other data. Since the version is passed at run time and based on that the map is built, will it be appropriate to have a separate build function inside the service class which can be called to setup all the required things?
Any alternative to this approach?

答案1

得分: 0

If I understand the issue correctly, it looks like a case of sequential coupling. Consider a modified design of the class.

The simplest option is to add the required map as a method parameter to the generateData method:

generateData(json, map) {
    // uses map
}
英文:

If I understand the issue correctly, it looks like a case of sequential coupling. Consider a modified design of the class.

The simplest option is to add the required map as a method parameter to the generateData method:

generateData(json, map) {
    // uses map
}

答案2

得分: 0

有很多方法可以解决这个问题。

另一个简单的方法是为 ServiceClass 添加另一个以 Map 为参数的构造函数:

// 糟糕的命名 - 希望这只是示例。太泛泛了;没有信息。
public class ServiceClass {

    private Map<X, Y> map;  // 你没有使用泛型或正确声明。

    public ServiceClass() { this(null); }

    public ServiceClass(Map<X, Y> m) {
        // 不要将私有变量设置为可变参数。这样做会破坏封装性。创建一个副本。
        this.map = (m != null) ? new HashMap<>(m) : new HashMap<>();
    }

    void generateFile(version) {
        String rVersion = fetchRversion(version);
        String json = makeApiCall(url + rVersion);
        // 使用 this.map
        generateData(json)
    }

    void generateData(json) {
        // 使用 this.map
    }
}

你的 JUnit 测试可以实例化 Map 并将其传递给 ServiceClass 进行测试。

英文:

There are lots of ways to solve this.

Another easy one would be to have another constructor for the ServiceClass that takes a Map as an argument:

// Poor names - I hope these are just examples.  Too generic; no information.
public class ServiceClass {

    private Map<X, Y> map;  // You don't use generics or declare properly.

    public ServiceClass() { this(null); }

    public ServiceClass(Map<X, Y> m) {
        // Never set a private variable equal to a mutable parameter.  You break encapsulation when you do.  Make a copy.
        this.map = (m != null) ? new HashMap<>(m) : new HashMap<>();
    }

    void generateFile(version) {
        String rVersion = fetchRversion(version);
        String json = makeApiCall(url + rVersion);
        // use this.map
        generateData(json)
    }

    void generateData(json) {
        // uses this.map
    }
}

Your JUnit test can instantiate the Map and pass it to the ServiceClass for the test.

huangapple
  • 本文由 发表于 2023年5月25日 20:35:39
  • 转载请务必保留本文链接:https://go.coder-hub.com/76332328.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定