休息控制器单元测试

时间:2016-10-27 16:10:15

标签: java spring rest unit-testing junit

我试图为Rest Controller进行单元测试。我为数据库访问管理器做了一个存根(〜mock),效果很好。我唯一的问题是,当我开始我的单元测试时,它不会启动应用程序。

如何从单元测试中启动应用程序?

我使用的是弹簧4.2.3,弹簧靴1.3.7,junit 4.12。

以下是我的课程:

TestRestController

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(locations = "classpath:/META-INF/spring/mvc/mvc-test-context.xml")
public class RestControllerTest extends AbstractTransitionnalTest {

  @Autowired
  private IManager Manager;

  @Test
  public void getTestSingleItem(){
    Item itm = myTestItemPreInitiallized;
    Manager.save(itm);
    List<Map> apiResponse = restTemplate.getForObject(networkAddress + "/items", List.class);
    // Assertions on apiResponse
  }
}

RestController:

@RestController
@RequestMapping("/items")
class RestController {

  @Autowired
  private IManager Manager;

  // Controller content
}

mvc-test-context.xml中的bean

<bean
        id="IManager"
        class="com.service.ManagerStub">
</bean>
<bean
        id="RestController"
        class="com.controller.RestController">
</bean>

包含主要

的应用程序类
@Configuration
@EnableAutoConfiguration
@EnableTransactionManagement
@ImportResource({ "classpath:/META-INF/spring/context-application.xml" })
public class Application {

如果我现在运行它,应用程序类没有启动,我得到以下错误: GET请求地址的I / O错误:拒绝连接

如果您没有确切的解决方案,或者想提出另一种方法来执行此操作或解决方法,我希望将ManagerStub插入@Autowired只有在我启动测试时,管理员才会改为Manager

3 个答案:

答案 0 :(得分:5)

我们可以使用MockitoJUnitRunner和Spring的MockMvcBuilders类的组合来编写Spring REST Controller的单元测试。

我已经更改了您的代码并在下面引用它来为您的REST控制器编写JUnits。

import java.util.ArrayList;
import java.util.List;

import org.junit.Before;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.mockito.runners.MockitoJUnitRunner;
import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;

import com.fasterxml.jackson.databind.ObjectMapper;

import biz.cogitare.framework.controllers.advices.ExceptionControllerAdvice;

@RunWith(MockitoJUnitRunner.class)
public class RestControllerTest {

    private MockMvc mockMvc;

    private Item item;

    private String itemJSON;

    @Mock
    private Manager manager;

    @InjectMocks
    private RestController restController = new RestController();

    @Before
    public void setUp() throws Exception {
        MockitoAnnotations.initMocks(this);

        mockMvc = MockMvcBuilders.standaloneSetup(restController)
                .setMessageConverters(new MappingJackson2HttpMessageConverter());

         Item item = myTestItemPreInitiallized;

        itemJSON = new ObjectMapper().writeValueAsString(itm);
    }

    @Test
    public void testQuerySuccess() throws Exception {

        List<Item> items = new ArrayList<>();
        items.add(item);

        Mockito.when(manager.findItems()).thenReturn(items);

        mockMvc.perform(get("/items?itemId=1").accept(MediaType.APPLICATION_JSON)).andExpect(status().isOk());
                //.andExpect(jsonPath("$[0].id", is(1)))
                //.andExpect(jsonPath("$[0].name", is("xyz")));

        Mockito.verify(manager).findItems();
    }


    @Test
    public void testInsertSuccess() throws Exception {

        Mockito.when(manager.insertOrUpdate(Mockito.any(Item.class))).thenReturn(item);

        mockMvc.perform(post("/items").contentType(MediaType.APPLICATION_JSON).content(itemJSON)
                .accept(MediaType.APPLICATION_JSON)).andExpect(status().isCreated());

        Mockito.verify(manager).save(Mockito.any(Item.class));
    }
}

答案 1 :(得分:1)

我使用以下命令注释我的集成REST JUnit测试:

@WebIntegrationTest

带有

的实际Application课程
@SpringBootApplication

(除了您展示的所有注释之外) 使用这些注释,Spring Boot负责在运行测试之前使用提供的配置启动应用程序。

编辑:根据the documentation,自{1.4}赞成@WebIntegrationTest后,@SpringBootTest已被弃用,但您使用1.3.7则没有问题。

答案 2 :(得分:0)

我正在尝试使用Mockito和Junit以及MockMvc测试方法来回答您的问题。

  • 我在这里对您当前的测试班进行了一些更改。

TestRestController

import static org.junit.Assert.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.springframework.http.MediaType;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import com.fasterxml.jackson.databind.ObjectMapper;

    @RunWith(SpringJUnit4ClassRunner.class)
    @SpringApplicationConfiguration(locations = "classpath:/META-INF/spring/mvc/mvc-test-context.xml")
    public class RestControllerTest extends AbstractTransitionnalTest {

      @Mock
      private IManager Manager;

        private MockMvc mockMvc;

        @Before
        public void setUp() throws Exception {
            initMocks(this);// this is needed for inititalization of mocks, if you use @Mock 
            RestController controller = new RestController(manager);
            mockMvc = MockMvcBuilders.standaloneSetup(controller).build();
        }

      @Test
      public void getTestSingleItem(){
        Item itm = yourTestItemPreInitiallized;
        Mockito.when(manager.save(Mockito.any(Item.class))).thenReturn(itm);

        mockMvc.perform(MockMvcRequestBuilders.post("/items")
                    .content(asJsonString(app))
                    .contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
                    .andExpect(status().isOk())
                    .andExpect(content().contentType("application/json;charset=UTF-8"));
        }

        public static String asJsonString(final Object obj) {
            try {
                return new ObjectMapper().writeValueAsString(obj);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
    }