Testing Katharsis JsonApi with MockMvc and Mockito

654 views Asked by At

I would like to test the behaviour configured by my Katharsis ResourceRepository (katharsis-spring 2.1.7):

import io.katharsis.queryParams.QueryParams;
import io.katharsis.repository.ResourceRepository;
import org.springframework.stereotype.Component;

@Component
public class UserResourceRepository implements ResourceRepository<UserDTO, String> {

    @Autowired
    private UserRepository databaseRepository;

    @Override
    public UserDTO findOne(String email, QueryParams queryParams) {
        return null;
    }

    @Override
    public Iterable<UserDTO> findAll(QueryParams queryParams) {
        return null;
    }

    @Override
    public Iterable<UserDTO> findAll(Iterable<String> iterable, QueryParams queryParams) {
        return null;
    }

    @Override
    public void delete(String email) {
    }

    @Override
    public UserDTO save(UserDTO s) {
        return null;
    }
}

I would like to test it in a similar way as I do it with normal, Spring Controllers, using Mockito to mock database repository and using MockMvc:

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;

import java.util.Optional;

import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

@RunWith(MockitoJUnitRunner.class)
public class UserJsonApiTest {

    @InjectMocks
    private UserResourceRepository resourceRepository;

    @Mock
    private UserRepository databaseRepository;

    private MockMvc mockMvc;

    @Before
    public void setup() {
        mockMvc = MockMvcBuilders.standaloneSetup(resourceRepository).build();
    }

    @Test
    public void first() throws Exception {
        Optional<UserEntity> user = Optional.of(new UserEntity().
                id(1).
                email("test@test").
                firstName("test first name").
                lastName("test last name").
                pass("test pass"));

        when(
                databaseRepository.
                        findOneByEmail(user.get().getEmail())).
                thenReturn(user);

        mockMvc.perform(
                get("/users/" + user.get().email())).
                andExpect(status().isOk())
        ;
    }

}

Obviously, this code doesn't work because my Katharsis UserResourceRepository is not really a Controller. So far I have learned (from logs) that it is actually using some filters mappings and class named io.katharsis.spring.KatharsisFilterV2.

Is there any way to use MockMvc for such test? If not - is there any other way I could test it without starting the whole server (with mocking)?

1

There are 1 answers

0
fmi On

You could use an embedded Server - like UndertowJaxrsServer - and inject the KatharsisFeature:

  1. Create a class (MyApp) which extends Application public static class MyApp extends Application { and deploy it to the embedded server server.deploy(MyApp.class);
  2. in this Class, overwrite getClasses and add a second class (KatharsisFeatureTest) which implements Feature KatharsisFeatureTest implements Feature
  3. in KatharsisFeatureTest you can then register a KatharsisFeature and there you can overwrite JsonServiceLocator and inject the mock.

Sound a little bit complicated, but works like charm :) Have a look at my implementation.

.

@RunWith(MockitoJUnitRunner.class)
public class EndpointResourceTest {
    @Mock
    private EndpointService endpointService;

    @InjectMocks
    private final static EndpointResourceV1 endpointRessource = new EndpointResourceV1();

    private static UndertowJaxrsServer server;

    @BeforeClass
    public static void beforeClass() throws Exception {
        server = new UndertowJaxrsServer();
        server.deploy(MyApp.class);
        server.start();
    }


    @Test
    public void testGetEndpoint() throws URISyntaxException {
        Mockito.when(endpointService.getEndpoint("SUBMIT")).thenReturn(new EndpointDTO("SUBMIT", "a", "b"));

        Client client = ClientBuilder.newClient();
        Response response = client.target(TestPortProvider.generateURL("/api/endpoints/SUBMIT"))
                .request(JsonApiMediaType.APPLICATION_JSON_API)
                .get();

        Assert.assertEquals(200, response.getStatus());
        String json = response.readEntity(String.class);
        Assert.assertTrue(json.contains("SUBMIT"));
        Assert.assertTrue(json.contains("a"));
        Assert.assertTrue(json.contains("b"));
        Mockito.verify(endpointService, Mockito.times(1)).getEndpoint("SUBMIT");
    }

    @AfterClass
    public static void afterClass() throws Exception {
        server.stop();
    }

    @ApplicationPath("/api")
    public static class MyApp extends Application {
        @Override
        public Set<Class<?>> getClasses() {
            HashSet<Class<?>> classes = new HashSet<Class<?>>();
            classes.add(KatharsisFeatureTest.class);
            return classes;
        }
    }

    public static class KatharsisFeatureTest implements Feature {
        @Override
        public boolean configure(FeatureContext featureContext) {
            featureContext
                .property(KatharsisProperties.RESOURCE_SEARCH_PACKAGE, "...")
                .register(new io.katharsis.rs.KatharsisFeature(
                    new ObjectMapper(), new QueryParamsBuilder(new DefaultQueryParamsParser()), new SampleJsonServiceLocator() {

                        @Override
                        public <T> T getInstance(Class<T> clazz) {
                            try {
                                if (clazz.equals(EndpointResourceV1.class)) {
                                    return (T) endpointRessource;
                                }

                                return clazz.newInstance();
                            }
                            catch (InstantiationException | IllegalAccessException e) {
                                throw new RuntimeException(e);
                            }
                        }

                    }));

            return true;
        }
    }

}