如何在下面的代码中模拟旧对象



我一直在使用mockito框架编写单元测试。我在下面有这个旧代码,如何在不重构的情况下在 approvalAction 方法中模拟 RemoteService 客户端对象?

public Map<String, String> approvalAction(long documentId, ActionCommandDTO request, FormData formData, byte[] prevData) {
    RemoteService client = getRemoteService();
    String urlString = String.format("formExtensions/%s?%s", formData.getId(), getAuthParam(formData.getRealm()));
    try {
        response = client.postEntity(urlString, String.class, approvalSvcRequestStr);
    } catch (Exception e) {
        // TODO: handle rollback properly for P2P
        handleApprovalActionFailed(documentId, request, formData, prevData);
    }
    return map;
}

private RemoteService getRemoteService() {
    RemoteServiceConfig remoteServiceConfig = (RemoteServiceConfig) this.serviceConfigRegistry.getServiceConfigs().get("approval");
    remoteServiceConfig.setClientID(clientId);
    remoteServiceConfig.setClientSecret(privateSecret);
    RemoteService remoteService = new RemoteService(remoteServiceConfig, authorizationHeaderServiceImpl);
    return remoteService;
}

为什么不通过构造函数使RemoteService可注入,但也允许默认构造函数?

class YourClass{
    private final RemoteService client;
    public YourClass(RemoteService client){
        this.client = client;
    }
    public YourClass(){
        RemoteServiceConfig remoteServiceConfig = (RemoteServiceConfig) this.serviceConfigRegistry.getServiceConfigs().get("approval");
        remoteServiceConfig.setClientID(clientId);
        remoteServiceConfig.setClientSecret(privateSecret);
        client = new RemoteService(remoteServiceConfig, authorizationHeaderServiceImpl);
    }
    // all of your other methods inside the class
}

当然,您必须调整已经存在的构造函数。 但是由于您没有向全班展示,这对我来说是不可能的。

这使您在YourClass的整个生命周期中拥有客户端的单个实例。


现在很容易嘲笑RemoteService.只需使用模拟客户端实例化YourClass

RemoteService mock = mock(RemoteService.class);
YourClass toTest = new YourClass(mock);

你不能模拟远程服务,因为它是在类中创建的。如果可能的话,将getRemoteService解压缩到另一个类,我们称之为NewClass。现在你可以模拟NewClass了。

public Map<String, String> approvalAction(long documentId, ActionCommandDTO request, FormData formData, byte[] prevData) {
    RemoteService client = NewClass.getRemoteService(params);
    ///
}

另一种方法是,如果你不想改变你的遗留代码,那就是扩展你的类(实现 approvalAction)覆盖 getRemoteService() 函数。在getRemoteService调用的新实现中创建模拟远程服务。您可以测试这个新类。

getRemoteService更改为protected,并使用子类覆盖它:

public class SomeService {
    public Map<String, String> approvalAction(long documentId, ActionCommandDTO request, FormData formData, byte[] prevData) {
    }

    // change here
    protected RemoteService getRemoteService() {
        RemoteServiceConfig remoteServiceConfig = (RemoteServiceConfig) this.serviceConfigRegistry.getServiceConfigs()
                .get("approval");
        remoteServiceConfig.setClientID(clientId);
        remoteServiceConfig.setClientSecret(privateSecret);
        RemoteService remoteService = new RemoteService(remoteServiceConfig, authorizationHeaderServiceImpl);
        return remoteService;
    }
}

public class TestSomeService extends SomeService {

    @Override
    protected RemoteService getRemoteService() {
        return new MockService();
    }
}

相关内容

  • 没有找到相关文章

最新更新