无法管理测试休息模板帮助程序类

时间:2017-12-12 17:37:11

标签: java spring unit-testing testing spock

我正在尝试一个多小时来测试这门课程。对于方法等的整个组件来说,它是如此丑陋。我喜欢一些建议如何进行更好的测试或重构类以使其更容易测试。我还想不出办法。

要测试的课程

@Slf4j
public final class HistoryRestService {
  static RestTemplate restTemplate = new RestTemplate();

  public static Optional<List<History>> findLatestHistories() {
    String url = buildUrl();
    ResponseEntity<History[]> responseEntity = null;
    try {
      responseEntity = restTemplate.getForEntity(url, History[].class);
    } catch (ResourceAccessException e) {
      log.warn("No connection to History persistence. Please check if the history persistence started up properly");
      return Optional.empty();
    }
    History[] histories = responseEntity.getBody();
    return Optional.of(Arrays.asList(histories));
  }

  private static String buildUrl() {
    StringBuilder stringBuilder = new StringBuilder();
    stringBuilder.append("http://");
    stringBuilder.append("localhost");
    stringBuilder.append(":8081");
    stringBuilder.append("/history/get");
    return stringBuilder.toString();
  }

  // For Testing
  static void setRestTemplate(RestTemplate restTemplate) {
    HistoryRestService.restTemplate = restTemplate;
  }
}

Spock测试失败

class HistoryRestServiceTest extends Specification {
    def "test findLatestHistories"() {
        given:
        History mockedHistory = Mock()
        HistoryRestService uut = new HistoryRestService()
        History[] expected = [mockedHistory]
        RestTemplate mockedRestTemplate = Stub()
        ResponseEntity<History> mockedResponseEntity = Stub()

        mockedResponseEntity.getBody() >> expected
        mockedRestTemplate.getForEntity(_) >> mockedResponseEntity

        uut.setRestTemplate(mockedRestTemplate)

        when:
        def actual  = uut.findLatestHistories()
        then:
        actual.get() == expected

    }
}

1 个答案:

答案 0 :(得分:0)

我建议使用真正的依赖注入(spring / guice / cdi)而不是静态变量。

此外,您应该考虑要测试的内容,是正确的请求和解析网络调用,然后使用mockserverwiremock之类的内容编写集成测试以获得整体堆。或者,如果您只关心结果处理,那么您可以将与RestTemplate交互的代码移动到单独的方法中,并使用partial mocking来模拟此方法。我建议使用真正的集成测试,但为了一个例子,这应该可行,但我没有验证代码。

@Slf4j
public class HistoryRestService {
  private final RestTemplate restTemplate;

  public HistoryRestService() {
     restTemplate = new RestTemplate();
  }

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

  public Optional<List<History>> findLatestHistories() {
    try {
      return Optional.of(Arrays.asList(getLatestHistories(buildUrl())));
    } catch (ResourceAccessException e) {
      log.warn("No connection to History persistence. Please check if the history persistence started up properly");
      return Optional.empty();
    }
  }

  History[] getLatestHistories(String url) throws {
    ResponseEntity<History[]> responseEntity = null;
    responseEntity = restTemplate.getForEntity(url, History[].class);
    return responseEntity.getBody()
  }

  private String buildUrl() {
    StringBuilder stringBuilder = new StringBuilder();
    stringBuilder.append("http://");
    stringBuilder.append("localhost");
    stringBuilder.append(":8081");
    stringBuilder.append("/history/get");
    return stringBuilder.toString();
  }
}


class HistoryRestServiceTest extends Specification {
    @Subject
    HistoryRestService uut = Spy()

    def "test findLatestHistories"() {
        given:
        History[] expected = [mockedHistory]

        when:
        def actual  = uut.findLatestHistories()

        then:
        actual.get() == expected
        1 * uut.getLatestHistories(_ as String) >> expected
    }

    def "test findLatestHistories returns empty on exceptions"() {
        given:
        History[] expected = [mockedHistory]

        when:
        def actual  = uut.findLatestHistories()

        then:
        !actual.present
        1 * uut.getLatestHistories(_ as String) >> {throw new ResourceAccessException()}
    }
}