英文:
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论