skinny85 / specnaz

Library for writing beautiful, RSpec/Jasmine/Mocha/Jest-style specifications in Java, Kotlin and Groovy
Other
34 stars 8 forks source link

Better Mockito integration #1

Closed skinny85 closed 6 years ago

skinny85 commented 7 years ago

In "regular" JUnit, you can use the MockitoJUnitRunner to avoid explicitly initializing mocks (among other things - see the JavaDocs linked above for details):

 @RunWith(MockitoJUnitRunner.class)
 public class ExampleTest {

     @Mock
     private List list;

     @Test
     public void shouldDoSomething() {
         list.add(100);
     }
 }

There was a Feature Request to add this capability to Specnaz.

skinny85 commented 7 years ago

Right now, you can save some boilerplate by using MockitoAnnotations.initMocks:

import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.specnaz.junit.SpecnazJUnit;

import java.util.List;

import static org.assertj.core.api.Assertions.assertThat;

public class UsingMockitoSpec extends SpecnazJUnit {
    @Mock
    List<String> list;

    {
        describes("A Mockito test", it -> {
            it.beginsEach(() -> {
                MockitoAnnotations.initMocks(this);
            });

            it.should("initialize the mocks correctly", () -> {
                assertThat(list.get(99)).isNull();
            });
        });
    }
}

Whatever design we come up with, I would assume it would do something very similar to above. The question then becomes, is it worth to develop a feature just to save one beginsEach method? (I don't know; this is not a sarcastic question, I'm honestly curious whether it's a good trade-off).

Another thing is that there might be legitimate cases when you want to init the mocks in a beginsAll instead of a beginsEach - the implemented solution would have to allow you to switch between the 2 modes (I would most likely make the beginsEach behavior the default).

Pros of developing this solution:

Cons:

If we do choose to implement this feature, probably the MockitoSession API would come in handy.

skinny85 commented 6 years ago

This has been done, but in a rather different way than I originally planned. It's possible thanks to the JUnit Rules support that has been added in version 1.3.

Example:

public class MockitoExampleSpec extends SpecnazJUnit {
    public Rule<MockitoRule> mockitoRule = Rule.of(() -> MockitoJUnit.rule());

    @Mock
    private List<Integer> listMock;

    {
        describes("Using the JUnit Mockito Rule in Specnaz", it -> {
            it.should("initialize fields annotated with @Mock", () -> {
                when(listMock.get(0)).thenReturn(400 + 56);

                assertEquals(456, (int) listMock.get(0));
            });
        });
    }
}

Because of that, I'm resolving this one.