在没有 setter 的情况下设置模拟字段 class

Set field of mock class without setter

我想用 spock 测试这个方法

public class MainService {   
  private final DLCRDDLPortType dlcrddlPortType;  
  public void startProcess(Application app) {          
        Holder<String> status = new Holder<>();     
        Holder<String> statusText = new Holder<>();          
        dlcrddlPortType.startProcess(app.getApplicationId(), status, statusText);     
        if (status.value.equals(FAIL_RESPONSE_STATUS)) {         
        throw new FailResponseException(String.format("Failed to get response with status %s and description %s", status.value, statusText.value));     

}}

public final class Holder<T> implements Serializable {

    public T value; 

    public Holder() {
    }    

    public Holder(T value) {
        this.value = value;
    }
}

status.value 为 null,没有 setter 我无法更改它,我无法使用构造函数创建它,因为我需要模拟。我该如何解决?

错误: 无法调用“String.equals(Object)”,因为“status.value”为空

我的测试:

private DLCRDDLPortType dlcrddlPortType
private MainService mainService
private Holder status
private Holder statusText

void setup() {
    status = GroovyMock()
    dlcrddlPortType = Mock()
    mainService= new MainService(dlcrddlPortType)
}

def "startProcess success"() {
    
    given:
    def appId = 171l     
    ReflectionTestUtils.setField(status, "value", "SUCCESS")
    def app = Application.builder().applicationId(appId).build()
   
    when:
    mainService.startProcess(app)
    then:        
    1 * dlcrddlPortType.startProcess(appId, status, statusText)

}

我试图根据您的部分示例创建一个 MCVE。 重要的部分是:

            1 * dlcrddlPortType.startProcess(appId, _, _) >> { id, status, statusText ->
                status.value = "SUCCESS"
            }

有了这个,您可以使用响应生成器访问参数,并将值设置为状态持有者。

这里是稍微改编的例子:

public class MainService {   
    private DLCRDDLPortType dlcrddlPortType;  
    public void startProcess(Application app) {          
        Holder<String> status = new Holder<>();     
        Holder<String> statusText = new Holder<>();          
        dlcrddlPortType.startProcess(app.getApplicationId(), status, statusText);     
        if (status.value.equals("FAIL_RESPONSE_STATUS")) {         
            throw new IllegalStateException(String.format("Failed to get response with status %s and description %s", status.value, statusText.value));     
        }
    }
}

class Application {
    long applicationId
}

interface DLCRDDLPortType {
    void startProcess(long applicationId, Holder<String> status, Holder<String> statusText)
}


public final class Holder<T> implements Serializable {

    public T value; 

    public Holder() {
    }    

    public Holder(T value) {
        this.value = value;
    }
    
    public void setValue(T value) {
        this.value = value;
    }
}

class ASpec extends Specification {

    def "startProcess success"() {
        given:
        DLCRDDLPortType dlcrddlPortType = Mock()
        MainService mainService = new MainService(dlcrddlPortType: dlcrddlPortType)
        long appId = 171l     
        def app = new Application(applicationId: appId)

        when:
            mainService.startProcess(app)
        
        then:        
            1 * dlcrddlPortType.startProcess(appId, _, _) >> { id, status, statusText ->
                status.value = "SUCCESS"
            }
    }
}

Groovy Console

试试