使用 spring boot、kotlin 和 junit 进行休息控制器单元测试
Posted
技术标签:
【中文标题】使用 spring boot、kotlin 和 junit 进行休息控制器单元测试【英文标题】:Rest controller unit testing with spring boot, kotlin and junit 【发布时间】:2018-10-17 01:39:20 【问题描述】:我目前正在开发一个带有 spring boot 的网站,kotlin,我正在尝试以 xml 格式阅读 Google Trends Rss 提要并将它们解析为 Json。 我想添加单元测试来测试我的控制器,但我不知道到底要测试什么。
这是我的数据类:
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)
我的问题是:我应该测试什么?以及如何测试输出是否写入?
【问题讨论】:
【参考方案1】:由于控制器依赖外部 URL 来检索新闻提要的详细信息,因此您很难对控制器进行单元测试。
我会将与外部 URL 的交互提取到一个单独的服务中,然后将该服务自动连接到您的控制器中。这将允许 yopu 在控制器的单元测试中使用此服务的 Mock 实现,然后您可以注入已知的提要项目并确保来自控制器的响应是正确的。
【讨论】:
【参考方案2】:我将控制器从服务中分离出来:
休息控制器:
@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 'One-Sided' <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)
那么传递包含提要的本地路径的文件是否正确?
【讨论】:
这看起来是一种合理的方法,因为它为您提供了一致且可重复的测试用例。以上是关于使用 spring boot、kotlin 和 junit 进行休息控制器单元测试的主要内容,如果未能解决你的问题,请参考以下文章
是否可以在 Spring Boot 中使用 @Transactional 和 kotlin 协程?
MapStruct 不使用 Kotlin 和 Spring Boot 自动装配,使用 Gradle 构建
如何在 Spring Boot 和 Spring WebFlux 中使用“功能 bean 定义 Kotlin DSL”?