sizovs / PipelinR

PipelinR is a lightweight command processing pipeline ❍ ⇢ ❍ ⇢ ❍ for your Java awesome app.
https://github.com/sizovs/PipelinR
MIT License
420 stars 59 forks source link

Mocking PipelinR to testing controllers #14

Closed gustavodaquino closed 4 years ago

gustavodaquino commented 4 years ago

Hello, is there any example of unit test using the Pipeline object with MVC controllers?

Regards!

sizovs commented 4 years ago

Hi @gustavodaquino

You can easily unit test controllers that use PipelinR. SincePipeline is an interface that can be easily mocked, you should always use it in your MVC controllers and never talk to Pipelinr class directly. If you use Mockito, here is how it's gonna look:

// given:
var pipeline = mock(Pipeline.class);
var someCommand = new SomeCommand();
var someResponse = new SomeResponse();
when(pipeline.send(someCommand)).thenReturn(someResponse);

// and
var controller = new SomeMvcController(pipeline);

// when 
// you do something with the controller

// then
// something happens

Let me know if you need more examples. I am ready to help.

– Eduards

gustavodaquino commented 4 years ago

Thanks, @sizovs , but I still have doubts:

I'm trying to mock it in a Spring Boot project. On my controllers, I'm injecting a Pipeline instance via constructor as follow:

@RequiredArgsConstructor
@RequestMapping("/api/v1/my")
@RestController
public class MyController {

    private final Pipeline pipeline;

(...)

    @GetMethod
    public Boolean get() {

        var foo = new Foo();

        // during testing, it returns null
        return pipeline.send(foo);
    }

And at the Test Class, I'm using the @MockBean to create an instance of Pipeline, and the @WebMvcTest to perform and assert the operations.

@RunWith(SpringRunner.class)
@WebMvcTest(MyController.class)
public class MyControllerTests {

    @Autowired
    private MockMvc mvc;

    @Autowired
    private ObjectMapper mapper;

    @MockBean
    private Pipeline pipelineMock;

(...)

    @Test
    public void foo() throws Exception {

        when(pipelineMock.send(new Foo()).thenReturn(true);

        mvc.perform(MockMvcRequestBuilders
                .get("/api/v1/my")
                .contentType(MediaType.APPLICATION_JSON)
                .accept(MediaType.APPLICATION_JSON))
                .andExpect(status().isOk());
    }

But, the result of the mocked Pipeline is always null. Can you give me an example using a Spring Boot controller and the framework annotations for testing?

Maybe you can add these examples on the documentation, for future reference.

Regards!

gustavodaquino commented 4 years ago

Thanks, @sizovs , but I still have doubts:

I'm trying to mock it in a Spring Boot project. On my controllers, I'm injecting a Pipeline instance via constructor as follow:

@RequiredArgsConstructor
@RequestMapping("/api/v1/my")
@RestController
public class MyController {

    private final Pipeline pipeline;

(...)

    @GetMethod
    public Boolean get() {

        var foo = new Foo();

        // during testing, it returns null
        return pipeline.send(foo);
    }

And at the Test Class, I'm using the @MockBean to create an instance of Pipeline, and the @WebMvcTest to perform and assert the operations.

@RunWith(SpringRunner.class)
@WebMvcTest(MyController.class)
public class MyControllerTests {

    @Autowired
    private MockMvc mvc;

    @Autowired
    private ObjectMapper mapper;

    @MockBean
    private Pipeline pipelineMock;

(...)

    @Test
    public void foo() throws Exception {

        when(pipelineMock.send(new Foo()).thenReturn(true);

        mvc.perform(MockMvcRequestBuilders
                .get("/api/v1/my")
                .contentType(MediaType.APPLICATION_JSON)
                .accept(MediaType.APPLICATION_JSON))
                .andExpect(status().isOk());
    }

But, the result of the mocked Pipeline is always null. Can you give me an example using a Spring Boot controller and the framework annotations for testing?

Maybe you can add these examples on the documentation, for future reference.

Regards!

Solved! I forgot to send any() on the mocked Pipeline.

when(pipelineMock.send(any(Foo.class)).thenReturn(true);

Thanks for your insight, and congratulations for your awesome and very useful library!