0
votes

I have a Java service which has few things injected by Guice.

public class RecoveryServiceImpl implements RecoveryService {
    @Inject
    public RecoveryServiceImpl(SessionInstanceCache sessionInstanceCache, AttendeeCache attendeeCache, MessagingStreamConfiguration messagingConfig) {
        this.sessionInstanceCache = sessionInstanceCache;
        this.attendeeCache = attendeeCache;
        this.messagingConfig = messagingConfig;
    }

    @Override
    public SessionInstanceData recoverSessionInstance(SessionInstanceDto sessionInstance) {
        SessionInstanceData sessionInstanceData = SessionInstanceHelper.recoverSessionInstance(sessionInstance);

        if (sessionInstanceData.getDeepstreamServerKey() == null) {
            String dsKey = SessionInstanceHelper.pickRandomDeepstreamServerKey(
                sessionInstanceData, messagingConfig);

And this does:

public static String pickRandomDeepstreamServerKey(
        SessionInstanceData sessionInstanceData, MessagingStreamConfiguration dsConfig) {
    // NPE occurs here
    List<String> dsKeys = new ArrayList(dsConfig.getBaseUrls().keySet()); 

This is tested with Spock. I added the messagingConfig and now I am struggling making it mocked in a Spock test:

class RecoveryServiceImplTest extends Specification {

...
    MessagingStreamConfiguration msgConfig = Mock(MessagingStreamConfiguration);
    RecoveryService recoveryService = new RecoveryServiceImpl(sessionInstanceCache, attendeeCache, msgConfig);

    def "Recover session instance"() {
        ...
        def dsMap = new HashMap<String, URL>();
        dsMap.put("ds1", new URL("http://ilovemocking.com/"));

        when:
        msgConfig.getBaseUrls() >> dsMap;
        //msgConfig.getBaseUrls().keySet() >> new HashSet(){{add("ds1")}};
        recoveryService.recoverSessionInstance(sessionInstanceDto)

In the call to recoverSessionInstance(), I get a NPE because getBaseUrls() returns null.

I have tried other way, instantiating the msgConfig as a normal object (AKA "stubbing"), but same result.

How should I make Spock Mock to return the dsMap instead of null?

1
Could you attach the code of SessionInstanceHelper.recoverSessionInstance() to see which expression throws NPE? - Alexander Terekhov
Sure, I forgot. - Ondra Žižka
Please try to move msgConfig.getBaseUrls() >> dsMap from when block to then: 1 * msgConfig.getBaseUrls() >> dsMap - Opal
Another option is to: MessagingStreamConfiguration msgConfig = Mock(MessagingStreamConfiguration) { getBaseUrls() >> dsMap } but dsMap must be declared before the mock is defined. - Opal

1 Answers

0
votes

In the end, it was some issue with missing method in a dependency .jar (compared to what I saw as code). The NPE was coming from the Mock proxy rather than the expression itself. However it was hard to see in the stacktrace full of reflections.

I will delete the question in a while.