23 Temmuz 2019 Salı

SpringBoot Test @MockBeans Anotasyonu

Giriş
Bir sürü @MockBean yerine tek bir yerde tüm mock'ları tanımlamaya yarar. Açıklaması şöyle.
Container annotation that aggregates several @MockBean annotations.
Örnek
Elimizde şöyle bir kod olsun.
@ExtendWith(SpringExtension.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class EndpointsTest implements ApplicationContextAware {

    @MockBean
    ComponentA componentA;
    @MockBean
    ComponentB componentB;

...
Şöyle yaparız.
@Configuration
@MockBeans({YourComponentSuperclass.class})
public class TestConfig {
}

SpringTest MockMvc Sınıfı

Giriş
Şu satırı dahil ederiz
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
Bu sınıf belki de Spring 'in en önemli test sınıflarından birisi. Web katmanını test edebilmeyi sağlar. Bu sınıf sayesinde post ve get isteği gönderebiliriz

- Bu sınıf test metoduna inject edilir.
- get ve post isteklerini oluşturmak için MockMvcRequestBuilders kullanılır
- İstek MockMvc.perform() ile gönderilir.
- Döndürülen sonuç ResultActions arayüzü cinsindendir. Bu arayüzün sınıfının andExpect() metodları ile test edilir.

Örnek
Eğer test @WebMvcTest ise bir şey yapmaya gerek yok. Sadece şöyle yaparız
@RunWith(SpringRunner.class)
@WebMvcTest(StudentServer.class)
public class RestTest {

  @Autowired
  private MockMvc mockMvc;
  ...
}
Örnek
Eğer testimiz basit bir test ise @AutoConfigureMockMvc lazım. Şöyle yaparız
@SpringBootTest
@AutoConfigureMockMvc
class GraphqldemoApplicationTests {
  @Autowired
  MockMvc mockMvc;
  ...
}
Delete Örneği
Şöyle yaparız
mockMvc.perform(MockMvcRequestBuilders.delete("/demo/vehicles/AD23E5R98EFT3SL00")
.contentType(MediaType.APPLICATION_JSON)) .andExpect(status().isNoContent());
Get Örneği
Şöyle yaparız
mockMvc.perform(MockMvcRequestBuilders.get("/demo/vehicles")
  .contentType(MediaType.APPLICATION_JSON))
  .andExpect(status().isOk())
  .andExpect(jsonPath("$", hasSize(2)))
  .andExpect(jsonPath("$[0].vin", is("AD23E5R98EFT3SL00")))
  .andExpect(jsonPath("$[0].make", is("Ford")))
  .andExpect(jsonPath("$[1].vin", is("O90DEPADE564W4W83")))
  .andExpect(jsonPath("$[1].make", is("Volkswagen"))
);
Post Örneği
Şöyle yaparız
String vehicleJsonString = this.mapper.writeValueAsString(vehicle);
ResultActions resultActions =
mockMvc.perform(MockMvcRequestBuilders.post("/demo/create/vehicle/") .contentType(MediaType.APPLICATION_JSON) .content(vehicleJsonString)) .andExpect(status().isBadRequest());
Put Örneği
Şöyle yaparız
MockHttpServletRequestBuilder builder = MockMvcRequestBuilders
.put("/demo/update/vehicle/AD23E5R98EFT3SL00", vehicle) .contentType(MediaType.APPLICATION_JSON_VALUE) .accept(MediaType.APPLICATION_JSON).characterEncoding("UTF-8") .content(this.mapper.writeValueAsBytes(vehicle)); mockMvc.perform(builder) .andExpect(status().isAccepted()) .andExpect(jsonPath("$.vin", is("AD23E5R98EFT3SL00"))) .andExpect(MockMvcResultMatchers.content().string(mapper.writeValueAsString(vehicle)));
andExpect metodu

Örnek
Post isteğine karşılık sonuç olarak döndürülen json'ı beklenen json ile karşılaştırmak için şöyle yaparız
@Test
void listFoods() {
  String expectedResponse = "...";
  mockMvc.perform(MockMvcRequestBuilders.post("/graphql")
    .content("{\"query\":\"{ foods { id name isGood } }\"}")
    .contentType(MediaType.APPLICATION_JSON)
    .accept(MediaType.APPLICATION_JSON))
    .andExpect(MockMvcResultMatchers.status().isOk())
    .andExpect(MockMvcResultMathers.content().json(expectedResponse))
    .andReturn();
}
Örnek
Şöyle yaparız
@Test
public void testGenerateStudent() throws Exception {

  Student student = new Student();
  student.setName("TestStudent");
  Mockito.when(studentService.getRandomStudent()).thenReturn(student);

  mockMvc.perform(MockMvcRequestBuilders.get("/generate-student"))
    .andExpect(MockMvcResultMatchers.status().isOk())
    .andDo(print())
    .andExpect(MockMvcResultMatchers.jsonPath("$.name").isNotEmpty());

}
perform metodu
ResultActions nesnesi döner.

Örnek - post
Şöyle yaparız.
private MockMvc mockMvc;

MvcResult result = 
mockMvc.perform(MockMvcRequestBuilders.post("/menus/update")
  .param("menuId", "1")
  .param("menuName", "menu1"))
.andExpect(MockMvcResultMatchers.status().isOk())
.andExpect(MockMvcResultMatchers.content().contentType("text/plain;charset=ISO-8859-1"))
.andExpect(MockMvcResultMatchers.content().string("true"))
.andDo(MockMvcResultHandlers.print())
.andReturn();
Örnek  - post
json post etmek için şöyle yaparız.
mockMvc.perform(MockMvcRequestBuilders.post("/objectservice/schema/")
  .contentType("application/json")
  .content(objectMapper.writeValueAsString(...)))
  .andExpect(status().isOk());
Örnek
multipart file post etmek için şöyle yaparız.
File file = new File("path/to/file.jpg");
MockMultipartFile upload = new MockMultipartFile("file", "file.jpg",
                                 MediaType.IMAGE_JPEG_VALUE,
                                 Files.readAllBytes(file.toPath()));
mockMvc.perform(multipart("/save/image").file(upload)).andExpect(status().isNoContent());