如何模拟依赖于输入值的依赖项?

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

}

通常,我们通过将它们作为参数传递并在 Junit/Mockito 中模拟它们来模拟 SDKClient 之类的依赖项。但是,在这种情况下,我不能只传递它,因为 SDKClient 取决于传入的实际事件。还有一个未确定的客户端数量,一个对应 event 中的每条消息。我想对整个方法进行单元测试,但我事先不知道依赖关系。可能吗?

在这种情况下,您传入的是某种抽象了 new SDKClient 调用的函数:

interface SdkClientProvider {
    SDKClient(String user, String password);
}

在这种特殊情况下,如果您愿意,可以使用 BiFunction<String, String, SDKClient>

由于 new SDKClient 可能是此 class 的唯一“实时”实现,您甚至可以这样做:

class MyService {
    @Setter
    private BiFunction<String, String, SDKClient> createClient = SDKClient::new;

    ...
}

这种模式在依赖于系统时很常见java.time.Clock

(请注意,“创建、使用和处置服务对象”是一个非常有问题的设计,除非您坚持使用某些 badly-designed 外部库,否则它会要求重构。)