How to mock Mono.create

2019-08-18 14:45发布

问题:

I'm using the spock framework and need to return a mocked Mono from a Mono.create(..)

I've tried:

GroovyMock(Mono)

as well as

GroovyMock(Mono, global:true)
1 * Mono.create(_ as MonoSink) >> Mono.just(returnedValue)

But I get the message that there were too few assertions for the above code.

Here is the actual Mono.create code

Mono.create{ sink -> 
    myAPISoap.getStuffAsync(
            username, 
            password, 
            info, 
            { outputFuture -> 
                try {
                    sink.success(outputFuture.get())
                } catch(Exception e){
                    sink.error(e)
                } 
            }
    )
}

回答1:

In Spock, you can only mock static methods of Groovy classes, not Java classes. You can use PowerMock(ito) for Java classes in this case. Then your problem can be solved as follows:

@RunWith(PowerMockRunner.class)
@PrepareForTest(Mono.class)
public class MonoTest {
    @Test
    public void test() {
        //given:
        PowerMockito.spy(Mono.class);
        Mockito.when(Mono.create(...)).thenReturn(null);

        //when:
        Mono<?> mono = Mono.create(...);

        //then:
        PowerMockito.verifyStatic(Mono.class, Mockito.times(1));
        Mono.create(...);

        //assertions
    }
}


回答2:

Dmitry Khamitov already showed you how to use PowerMock in Java + JUnit, I want to complete the picture by providing an MCVE in Grovy + Spock for your convenience:

package de.scrum_master.stackoverflow.q56064582;

import reactor.core.publisher.Mono;

public class ReactorSample {
  public Mono<String> doSomething() {
    return Mono.just("foo");
  }
}
package de.scrum_master.stackoverflow.q56064582

import org.junit.runner.RunWith
import org.powermock.core.classloader.annotations.PrepareForTest
import org.powermock.modules.junit4.PowerMockRunner
import org.powermock.modules.junit4.PowerMockRunnerDelegate
import org.spockframework.runtime.Sputnik
import reactor.core.publisher.Mono
import spock.lang.Specification

import static org.mockito.Matchers.anyString
import static org.powermock.api.mockito.PowerMockito.mockStatic
import static org.powermock.api.mockito.PowerMockito.when

@RunWith(PowerMockRunner.class)
@PowerMockRunnerDelegate(Sputnik.class)
@PrepareForTest([Mono.class])
class ReactorSampleTest extends Specification {
  def "test me"() {
    given:
    def dummy = Mono.just("power-mocked")
    mockStatic(Mono.class)
    when(Mono.just(anyString())).thenReturn(dummy)
    def sut = new ReactorSample()

    expect:
    sut.doSomething() == dummy
  }
}

You can easily adapt it to other static Mono methods.