使用 spring 引导、kotlin 和 junit 进行休息控制器单元测试

Rest controller unit testing with spring boot, kotlin and junit

我目前正在开发一个带有 spring boot, kotlin 的网站,我正在尝试阅读 Google xml 格式的趋势 Rss 提要并将它们解析为 Json . 我想添加单元测试来测试我的控制器,但我不知道到底要测试什么。

这是我的数据class:

data class Rss (

    val title: String,
    val source: String,
    val image: String,
    val description: String,
    val url: String
)

这是我的休息控制器

@RestController
@RequestMapping(value="/rss")
class RssRestService {

   @GetMapping(value = "/list/item")
   @CrossOrigin("http://localhost:3000")
   fun rss(): List<Rss>? {

         val url = "https://trends.google.fr/trends/hottrends/atom/feed?pn=p1"
         val reader = XmlReader(URL(url))
         val feed: SyndFeed = SyndFeedInput().build(reader)
         return feed.entries.subList(1,6)
                 .map { entry -> Rss(
                 title = entry.title,
                 image = entry.foreignMarkup[1].content[0].value.substring(2),
                 source = entry.foreignMarkup[2].content[0].value,
                 description = entry.foreignMarkup[3].content[1].value.toString(),
                 url = entry.foreignMarkup[3].content[1].value
    ) }

}

到目前为止我所做的测试是

@RunWith(SpringRunner::class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class DemoApplicationTests {


    @Autowired
    lateinit var testRestTemplate: TestRestTemplate

    @Test
    fun contextLoads() {

    }

    @Test
    fun rssTest() {
        val result = testRestTemplate.getForEntity("/rss/list/item", String::class.java)
        Assert.assertNotNull(result)
        Assert.assertEquals(HttpStatus.OK, result.statusCode)

}

我的问题是:我应该测试什么?以及如何测试输出是否写入?

您很难对控制器进行单元测试,因为它依赖外部 URL 来检索新闻源的详细信息。

我会将与外部 URL 的交互提取到单独的服务中,然后将此服务自动连接到您的控制器中。这将允许 yopu 在控制器的单元测试中使用此服务的模拟实现,然后您可以注入已知的提要项并确保控制器的响应正确。

我从服务中分离了控制器:

休息控制器:

@RestController
@RequestMapping(value="/rss")

class RssRestService {
    @Autowired
    lateinit var rssService: RssService


    @GetMapping(value = "/list/item")
    @CrossOrigin("http://localhost:3000")

    fun rss(): List<Rss>? {

        val url = "https://trends.google.fr/trends/hottrends/atom/feed?pn=p1"
        return  rssService.getListRss(url)

    }

我的服务

@Component
class RssService{

    fun getListRss(url: String): List<Rss> {
        val reader = XmlReader(URL(url))
        val feed: SyndFeed = SyndFeedInput().build(reader)
        return feed.entries.subList(1,6)
                .map { entry -> Rss(
                        title = entry.title,
                        image = entry.foreignMarkup[1].content[0].value,
                        source = entry.foreignMarkup[2].content[0].value,
                        description = entry.foreignMarkup[3].content[1].value.toString(),
                        url = entry.foreignMarkup[3].content[5].value
                ) }
    }

然后为了测试,我创建了一个包含静态 rss 提要的文件,并将它的路径作为 url

传递
@Test
    fun listItemTest() {
        val result = rssService.getListRss("file:///Home/iroolApp/src/test/kotlin/com/iroolapp/demo/feeds")
        Assert.assertEquals("Iran Nuclear Deal", result[0].title)
        Assert.assertEquals("//t0.gstatic.com/images?q=tbn:ANd9GcTbU16JklJB3H_Ib3dUeu03_4HQPABuE8EthZQRUEG6JMFyDHYytTn-9wexe3E2yYOKO1K9c0Fl", result[0].image)
        Assert.assertEquals("New York Times", result[0].source)
        Assert.assertEquals("Trump Withdraws US From &#39;One-Sided&#39; <b>Iran Nuclear Deal</b>", result[0].description)
        Assert.assertEquals("https://www.nytimes.com/2018/05/08/world/middleeast/trump-iran-nuclear-deal.html", result[0].url)

    }

那么传递一个包含提要的本地路径的文件是否正确?