Spock 测试中未返回存根对象方法值
Stubbed object method value not returned in Spock test
我是 Spock 框架的新手,正在编写一个测试用例,我试图在其中模拟一个名为 QueryDatabase
的 class
public class QueryDatabase {
public BigInteger countRecords(Instant start, Instant end) {
Flux<CountRecord> countValue = query("select * from users");
Optional<Object> value = Optional.ofNullable(countValue.blockFirst()).map(CountRecord::getValue);
BigInteger count = value.filter(BigInteger.class::isInstance)
.map(BigInteger.class::cast).orElse(BigInteger.valueOf(0));
return count
}
public Flux<CountRecord> query(String query) {
}
}
但是下面的测试用例是检查 countRecords(Instant, Instant) 返回的值总是给出 0,所以这意味着 when[=24] 中返回的值=]节
recordCount.query(_) >> Flux.just(CountRecord.builder().value(new BigInteger(133)).build())
没有被使用,似乎 recordCount.query(_) >> Flux.empty()
也没有任何影响,它总是 returns 默认的 BigInteger 值 0
def "record count"() {
given:
def now = Instant.now()
def last10Minutes = now.minus(10, ChronoUnit.MINUTES);
def recordCount = Stub(QueryDatabase)
when: "query returning empty flux"
recordCount.query(_) >> Flux.empty()
then:
recordCount.countRecords(last10Minutes, now) == 0
when: "query returning the count record"
recordCount.query(_) >> Flux.just(CountRecord.builder().value(new BigInteger(133)).build())
then:
recordCount.countRecords(last10Minutes, now) == 133
}
我是不是做错了什么?
您的代码存在几个问题。
- 您尝试在
when
块中设置一些存根
- 您在
then
版块 中执行了您的操作
- 您尝试重新定义存根
请参阅 Combining Mocking and Stubbing 了解其工作原理。
def "record count"() {
given:
def now = Instant.now()
def last10Minutes = now.minus(10, ChronoUnit.MINUTES);
def recordCount = Spy(QueryDatabase)
when: "query returning empty flux"
def result = recordCount.countRecords(last10Minutes, now)
then:
1 * recordCount.query(_) >> Flux.empty()
result == 0
when: "query returning the count record"
def 2ndResult = recordCount.countRecords(last10Minutes, now) == 133
then:
1 * recordCount.query(_) >> Flux.just(CountRecord.builder().value(new BigInteger(133)).build())
2ndResult == 133
}
或者,您可以将其拆分为数据驱动的功能
def "record count"(BigInteger result, Flux input) {
given:
def now = Instant.now()
def last10Minutes = now.minus(10, ChronoUnit.MINUTES);
def recordCount = Spy(QueryDatabase)
recordCount.query(_) >> input
expect:
recordCount.countRecords(last10Minutes, now) == result
where:
result | input
0 | Flux.empty()
133 | Flux.just(CountRecord.builder().value(new BigInteger(133)).build())
}
通常情况下,您会以相反的方式对参数进行排序,但由于通量如此冗长,我觉得这样更易读。
--
编辑:
我错过了您正在尝试对您正在测试的同一个对象进行存根,这只能通过 partial mocking 完成,并且通常表明应该重构代码。因此,将 Mock
/Stub
替换为 Spy
以进行部分模拟。
当您将 query
方法重写为 return 预期的 Flux
时,这种方式怎么样?在这种情况下,我建议进行 2 次测试:
def "record count when empty Flux"() {
given:
def now = Instant.now()
def last10Minutes = now.minus(10, ChronoUnit.MINUTES);
def recordCount = new QueryDatabase() {
@Overriden
public Flux<CountRecord> query(String query) {
Flux.empty()
}
}
expect:
recordCount.countRecords(last10Minutes, now) == 0
}
def "record count when non empty Flux"() {
given:
def now = Instant.now()
def last10Minutes = now.minus(10, ChronoUnit.MINUTES);
def recordCount = new QueryDatabase() {
@Overriden
public Flux<CountRecord> query(String query) {
Flux.just(CountRecord.builder().value(new BigInteger(133)).build())
}
}
expect:
recordCount.countRecords(last10Minutes, now) == 133
}
我是 Spock 框架的新手,正在编写一个测试用例,我试图在其中模拟一个名为 QueryDatabase
的 classpublic class QueryDatabase {
public BigInteger countRecords(Instant start, Instant end) {
Flux<CountRecord> countValue = query("select * from users");
Optional<Object> value = Optional.ofNullable(countValue.blockFirst()).map(CountRecord::getValue);
BigInteger count = value.filter(BigInteger.class::isInstance)
.map(BigInteger.class::cast).orElse(BigInteger.valueOf(0));
return count
}
public Flux<CountRecord> query(String query) {
}
}
但是下面的测试用例是检查 countRecords(Instant, Instant) 返回的值总是给出 0,所以这意味着 when[=24] 中返回的值=]节
recordCount.query(_) >> Flux.just(CountRecord.builder().value(new BigInteger(133)).build())
没有被使用,似乎 recordCount.query(_) >> Flux.empty()
也没有任何影响,它总是 returns 默认的 BigInteger 值 0
def "record count"() {
given:
def now = Instant.now()
def last10Minutes = now.minus(10, ChronoUnit.MINUTES);
def recordCount = Stub(QueryDatabase)
when: "query returning empty flux"
recordCount.query(_) >> Flux.empty()
then:
recordCount.countRecords(last10Minutes, now) == 0
when: "query returning the count record"
recordCount.query(_) >> Flux.just(CountRecord.builder().value(new BigInteger(133)).build())
then:
recordCount.countRecords(last10Minutes, now) == 133
}
我是不是做错了什么?
您的代码存在几个问题。
- 您尝试在
when
块中设置一些存根 - 您在
then
版块 中执行了您的操作
- 您尝试重新定义存根
请参阅 Combining Mocking and Stubbing 了解其工作原理。
def "record count"() {
given:
def now = Instant.now()
def last10Minutes = now.minus(10, ChronoUnit.MINUTES);
def recordCount = Spy(QueryDatabase)
when: "query returning empty flux"
def result = recordCount.countRecords(last10Minutes, now)
then:
1 * recordCount.query(_) >> Flux.empty()
result == 0
when: "query returning the count record"
def 2ndResult = recordCount.countRecords(last10Minutes, now) == 133
then:
1 * recordCount.query(_) >> Flux.just(CountRecord.builder().value(new BigInteger(133)).build())
2ndResult == 133
}
或者,您可以将其拆分为数据驱动的功能
def "record count"(BigInteger result, Flux input) {
given:
def now = Instant.now()
def last10Minutes = now.minus(10, ChronoUnit.MINUTES);
def recordCount = Spy(QueryDatabase)
recordCount.query(_) >> input
expect:
recordCount.countRecords(last10Minutes, now) == result
where:
result | input
0 | Flux.empty()
133 | Flux.just(CountRecord.builder().value(new BigInteger(133)).build())
}
通常情况下,您会以相反的方式对参数进行排序,但由于通量如此冗长,我觉得这样更易读。
-- 编辑:
我错过了您正在尝试对您正在测试的同一个对象进行存根,这只能通过 partial mocking 完成,并且通常表明应该重构代码。因此,将 Mock
/Stub
替换为 Spy
以进行部分模拟。
当您将 query
方法重写为 return 预期的 Flux
时,这种方式怎么样?在这种情况下,我建议进行 2 次测试:
def "record count when empty Flux"() {
given:
def now = Instant.now()
def last10Minutes = now.minus(10, ChronoUnit.MINUTES);
def recordCount = new QueryDatabase() {
@Overriden
public Flux<CountRecord> query(String query) {
Flux.empty()
}
}
expect:
recordCount.countRecords(last10Minutes, now) == 0
}
def "record count when non empty Flux"() {
given:
def now = Instant.now()
def last10Minutes = now.minus(10, ChronoUnit.MINUTES);
def recordCount = new QueryDatabase() {
@Overriden
public Flux<CountRecord> query(String query) {
Flux.just(CountRecord.builder().value(new BigInteger(133)).build())
}
}
expect:
recordCount.countRecords(last10Minutes, now) == 133
}