Тестирование Katharsis JsonApi с помощью MockMvc и Mockito
Я хотел бы проверить поведение, настроенное моим 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;
}
}
Я хотел бы протестировать его аналогично тому, как я это делаю с обычными контроллерами Spring, используя Mockito для имитации хранилища базы данных и используя 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())
;
}
}
Очевидно, этот код не работает, потому что мой пользовательский каталог Katharsis не является на самом деле контроллером. До сих пор я узнал (из журналов), что он на самом деле использует некоторые сопоставления фильтров и класс с именем io.katharsis.spring.KatharsisFilterV2.
Есть ли способ использовать MockMvc для такого теста? Если нет - есть ли другой способ проверить это без запуска всего сервера (с насмешками)?
1 ответ
Вы можете использовать встроенный сервер - например, UndertowJaxrsServer - и внедрить KatharsisFeature:
- Создайте класс (MyApp), который расширяет приложение
public static class MyApp extends Application {
и развернуть его на встроенном сервереserver.deploy(MyApp.class);
- в этом классе, переписать getClasses и добавить второй класс (KatharsisFeatureTest), который реализует функцию
KatharsisFeatureTest implements Feature
- в KatharsisFeatureTest вы можете зарегистрировать KatharsisFeature и там вы можете перезаписать JsonServiceLocator и ввести макет.
Звучит немного сложно, но работает как шарм:) Посмотрите на мою реализацию.
,
@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;
}
}
}