Home > Software engineering >  Set field of mock class without setter
Set field of mock class without setter

Time:12-27

I want to test this method with 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 is null, I cant change it without setter and I cant create it with constructor, beacause I need mock. How can I fix it?

Error: Cannot invoke "String.equals(Object)" because "status.value" is null

My test:

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)

}

CodePudding user response:

I tried to create an MCVE from you partial example. The important part is this:

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

With this you use the response generator to access the arguments, and set the value to the status holder.

Here is the slightly adapted example:

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"
            }
    }
}

Try it in the Groovy Console

  • Related