模拟子服务的REST请求

时间:2018-04-19 06:42:51

标签: java spring spring-boot integration-testing

我尝试使用@RestController在集成测试套件中测试MockMvc

@RunWith(SpringRunner.class)
@SpringBootTest
@WebAppConfiguration
public class WebControllerIT {

    @Autowired
    private WebApplicationContext wac;

    private MockMvc mockMvc;

    @Before
    public void setup() {
        this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
    }

    @Test
    public void getStatusReurnsSomething() throws Exception {
        this.mockMvc.perform(get("/status")).andExpect(status().isOk());
    }
}

@RestControllerWebController)调用注入的@ServiceRestClientService),它使用RestTemplate来调用另一个REST服务器。运行测试时会出现以下错误。

  

org.springframework.web.client.ResourceAccessException:I / O错误   GET请求" http://test123.com/42/status":test123.com;嵌套   异常是java.net.UnknownHostException:test123.com

我使用MockRestServiceServer进行@Service本身的集成测试,但不知道如何在@RestController的测试中实现此目的。

如何模拟RestTemplate的正确REST调用?

@RestController班。

@RestController
public class WebController {
    private final RestClientService service;

    @Autowired
    public WebController(RestClientService service) {this.service = service;}

    @GetMapping("/status")
    public String getStatus() {
        // extract pid from database ...
        int pid = 42;

        return this.service.getStatus(42);
    }
}

@Service班。

@Service
public class RestClientService {
    private final RestTemplate restTemplate;

    public RestClientService(RestTemplate restTemplate) {this.restTemplate = restTemplate;}

    public String getStatus(int pid) {
        String url = String.format("http://test123.com/%d/status", pid);
        return this.restTemplate.getForObject(url, String.class);
    }
}

2 个答案:

答案 0 :(得分:2)

集成/单元测试不起作用。这种测试的目的是贯穿你的代码,确保满足所有的业务需求,但不要打到其他系统或DB。在你的情况下,你应该要点击test123.com来获取数据。这里需要做的是你应该模仿那个方法。

public String getStatus(int pid) {
    String url = String.format("http://test123.com/%d/status", pid);
    return this.restTemplate.getForObject(url, String.class);
}

因此控件不会进入此方法,但会返回模拟数据(虚拟数据)。

例如,假设此方法返回有两种状态,您需要根据返回的字符串进行一些业务验证。在这种情况下,您需要编写2个集成测试并确保模拟方法返回2不同的值(虚拟值而不是命中该终点)

我们编写单元测试/集成测试的原因是为了确保您的整个代码按预期工作,而不是从您的代码中打到其他系统。

答案 1 :(得分:1)

如果你只想测试你的控制器层,你会这样做。

@RunWith(SpringRunner.class)
@SpringBootTest(classes = MockServletContext.class)
@WebAppConfiguration
public class WebControllerIT {

    private MockMvc mockMvc;

    private RestClientService service

    @Mock
    private RestTemplate restTemplate

    @Before
    public void setup() {
        MockitoAnnotations.initMocks(this);
        service = new RestClientService(restTemplate);
        WebController webController = new WebController(service);
        mvc = MockMvcBuilders.standaloneSetup(webController).build();
    }

    @Test
    public void getStatusReurnsSomething() throws Exception {
      //Mock the behaviour of restTemplate.
      doReturn("someString").when(restTemplate).getForObject(anyString(), anyString());
      this.mockMvc.perform(get("/status")).andExpect(status().isOk());
    }
}