Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ruby-on-rails-3/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何在下面的代码中模拟遗留对象?_Java_Mockito - Fatal编程技术网

Java 如何在下面的代码中模拟遗留对象?

Java 如何在下面的代码中模拟遗留对象?,java,mockito,Java,Mockito,我一直在使用mockito框架编写单元测试。 我有下面的遗留代码,如何在approvalAction方法中模拟RemoteService客户端对象而不重构它 public Map<String, String> approvalAction(long documentId, ActionCommandDTO request, FormData formData, byte[] prevData) { RemoteService client = getRemoteServi

我一直在使用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;
}
publicmap approvalAction(长documentId,ActionCommandDTO请求,FormData FormData,byte[]prevData){
RemoteService客户端=getRemoteService();
String urlString=String.format(“formExtensions/%s?%s”、formData.getId()、getAuthParam(formData.getRealm());
试一试{
response=client.postEntity(urlString、String.class、approvalSvcRequestStr);
}捕获(例外e){
//TODO:正确处理P2P的回滚
handleApprovalActionFailed(documentId、request、formData、prevData);
}
返回图;
}
私有远程服务getRemoteService(){
RemoteServiceConfig RemoteServiceConfig=(RemoteServiceConfig)this.serviceConfigRegistry.getServiceConfigs().get(“批准”);
remoteServiceConfig.setClientID(clientId);
remoteServiceConfig.setClientSecret(privateSecret);
RemoteService RemoteService=新的RemoteService(remoteServiceConfig,authorizationHeaderServiceImpl);
返回远程服务;
}

getRemoteService
更改为
受保护的
,并使用子类覆盖它:

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();
    }
}
公共类服务{
公共映射approvalAction(长文档ID、ActionCommandDTO请求、FormData FormData、字节[]prevData){
}
//在这里换车
受保护的RemoteService getRemoteService(){
RemoteServiceConfig RemoteServiceConfig=(RemoteServiceConfig)this.serviceConfigRegistry.getServiceConfigs()
.获得(“批准”);
remoteServiceConfig.setClientID(clientId);
remoteServiceConfig.setClientSecret(privateSecret);
RemoteService RemoteService=新的RemoteService(remoteServiceConfig,authorizationHeaderServiceImpl);
返回远程服务;
}
}
公共类TestSomeService扩展了SomeService{
@凌驾
受保护的RemoteService getRemoteService(){
返回新的MockService();
}
}

您不能模拟RemoteService,因为它是在您的类中创建的。如果可能的话,将getRemoteService提取到另一个类,让我们称之为NewClass。现在您可以模拟NewClass了

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

    RemoteService client = NewClass.getRemoteService(params);
    ///
}
publicmap approvalAction(长documentId,ActionCommandDTO请求,FormData FormData,byte[]prevData){
RemoteService client=NewClass.getRemoteService(参数);
///
}

另一种方法是,如果您不想更改遗留代码,则需要扩展类(实现approvalAction)覆盖getRemoteService()函数。在getRemoteService的新实现中,调用创建模拟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
的整个生命周期中,只有一个客户机实例


现在很容易模拟
远程服务
。只需使用模拟客户端实例化
YourClass

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

为什么要更改业务逻辑的代码以便在测试中模拟服务?@Stultuske,在某些情况下:在编写单元测试和涵盖测试场景时,我们可以在业务逻辑中找到一些问题点。因此,在考虑测试用例的同时重构代码可能是合理的。良好的单元测试有助于使体系结构变得更好,但这并不容易。为什么要包含“无需重构”的约束?@AkinerAlkan如果您进行测试驱动开发,那么您的测试是在实现之前编写的。话虽如此,我们谈论的不是(通过测试显示)出现故障的代码,而是更改业务代码以允许测试运行。使用
PowerMock
模拟
RemoteService
如何<代码>PowerMockito准确地说就是这种情况。