如何使用Spring 4和注释编写单元测试来验证异步行为?

SaW*_*SaW 7 spring unit-testing asynchronous

如何使用Spring 4和注释编写单元测试来验证异步行为?

因为我已经习惯了Spring的(旧的)xml风格),所以花了一些时间来解决这个问题.所以我想我回答自己的问题来帮助别人.

SaW*_*SaW 7

首先是公开异步下载方法的服务:

@Service
public class DownloadService {
    // note: placing this async method in its own dedicated bean was necessary
    //       to circumvent inner bean calls
    @Async
    public Future<String> startDownloading(final URL url) throws IOException {
        return new AsyncResult<String>(getContentAsString(url));
    }

    private String getContentAsString(URL url) throws IOException {
        try {
            Thread.sleep(1000);  // To demonstrate the effect of async
            InputStream input = url.openStream();
            return IOUtils.toString(input, StandardCharsets.UTF_8);
        } catch (InterruptedException e) {
            throw new IllegalStateException(e);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

接下来的测试:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
public class DownloadServiceTest {

    @Configuration
    @EnableAsync
    static class Config {
        @Bean
        public DownloadService downloadService() {
            return new DownloadService();
        }
    }

    @Autowired
    private DownloadService service;

    @Test
    public void testIndex() throws Exception {
        final URL url = new URL("http://spring.io/blog/2013/01/16/next-stop-spring-framework-4-0");
        Future<String> content = service.startDownloading(url);
        assertThat(false, equalTo(content.isDone()));
        final String str = content.get();
        assertThat(true, equalTo(content.isDone()));
        assertThat(str, JUnitMatchers.containsString("<html"));
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 我认为你应该真正测试`getContentAsString`,而不是`startDownloading`,否则你有效地测试Spring Framework本身,而不是你的应用程序的逻辑.此外,我知道它只是一个示例,但是一个流式传输URL内容的方法也可以保持未经测试,因为它只包含Java API调用,而不是业务逻辑. (2认同)