英文:
How to mock dependencies that depend on input value?
问题
我想对这样一个方法进行单元测试:
public String handleRequest(Event event) {
for(Message msg : event.getRecords()){
SDKClient client = new SDKClient(msg.getUser(), msg.getPassword());
String output = client.makeAPICall();
return output.toUpperCase();
}
}
通常情况下,我们会通过将依赖项(如 SDKClient
)作为参数传递,并在 Junit/Mockito 中进行模拟。但是,在这种情况下,我不能简单地传递它,因为 SDKClient
依赖于传入的实际事件。而且,每个事件中的每条消息都需要一个单独的客户端,数量不确定。我想将整个方法作为一个单元进行测试,但我事先不知道依赖关系。这种情况是否有可能?
英文:
I want to unit-test a method like this:
public String handleRequest(Event event) {
for(Message msg : event.getRecords()){
SDKClient client = new SDKClient(msg.getUser(), msg.getPassword());
String output = client.makeAPICall();
return output.toUpperCase();
}
}
}
Typically, we mock dependencies like SDKClient
by passing them in as arguments and mocking them in Junit/Mockito. However, in this case, I cannot just pass it because the SDKClient
depends on the actual events passed in. There is also an undetermined number of clients, one for each message in the event
. I want to unit test the method as a whole, but I do not know the dependencies in advance. Is it possible?
答案1
得分: 1
在这种情况下,您传入的是一种抽象new SDKClient
调用的函数:
interface SdkClientProvider {
SDKClient(String user, String password);
}
在这种特定情况下,您可以使用BiFunction<String, String, SDKClient>
。
由于new SDKClient
很可能是这个类唯一的“活”实现,您甚至可以这样做:
class MyService {
@Setter
private BiFunction<String, String, SDKClient> createClient = SDKClient::new;
...
}
在依赖于系统java.time.Clock
的情况下,经常看到这种模式。
(请注意,“创建、使用和处理服务对象”是一个非常值得质疑的设计,除非您被迫使用一些设计不良的外部库,否则最好进行重构。)
英文:
In that case, what you pass in is some kind of function that abstracts the new SDKClient
call:
interface SdkClientProvider {
SDKClient(String user, String password);
}
In this particular case, you could use BiFunction<String, String, SDKClient>
if you prefer.
As new SDKClient
is likely to be the only "live" implementation of this class, you can even do something like this:
class MyService {
@Setter
private BiFunction<String, String, SDKClient> createClient = SDKClient::new;
...
}
This pattern is commonly seen when depending on the system java.time.Clock
.
(Note that the "create, use, and dispose of a service object" is a very questionable design, and unless you're stuck with consuming some badly-designed external library, it's begging for refactoring.)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论