unit-testing - Spock 单元测试使用 spring 数据导致 Optional 中的错误
问题描述
我开始在 Spring Boot + Spring Data 项目中使用 Spock 框架执行测试。
当我尝试模拟我的存储库时会出现问题,但特别是在某些方法中返回是可选的。
Cannot invoke method orElse() on null object
java.lang.NullPointerException: Cannot invoke method orElse() on null object
at br.com.moskit.jivochat.service.UserService.getResponsible(UserService.groovy:37)
at br.com.moskit.jivochat.service.UserServiceTest.Retrive the responsible of interaction in JivoChat by configs of plugin item(UserServiceTest.groovy:65)
我的测试实现:
class UserServiceTest extends Specification {
UserService userService
void setup() {
userService = new UserService()
userService.userRepository = Mock(UserRepository)
GroovyMock(Optional)
}
def "Retrive the responsible of interaction in JivoChat by configs of plugin item"() {
given: 'that exist a collection of JivoChat interaction configurations'
List<Map> agents = null
Map configs = [responsibleId: 1]
userService.userRepository.findById(_) >> Optional.of(new User(username: "XPTO")).orElse("null")
when: 'the main method is called'
User user = userService.getResponsible(configs, agents)
then: 'the method get last agent and search in DB by e-mail'
1 * userService.userRepository.findById(_)
}
}
我的方法:
User getResponsible(Map configs, List<Map> agents) {
//Ommited...
Integer responsibleId = configs.responsibleId as Integer
Optional<User> userOptional = userRepository.findById(responsibleId)
User user = userOptional.orElse(null)
user
}
解决方案
这是一个经典的答案,答案可以在Spock 手册章节“Combining Mocking and Stubbing”中找到:
注意:同一方法调用的模拟和存根必须在同一交互中发生。
所以解决方案如下所示:
package de.scrum_master.stackoverflow.q66208875
class User {
int id
String username
}
package de.scrum_master.stackoverflow.q66208875
class UserRepository {
Optional<User> findById(int id) {
Optional.of(new User(id: id, username: "User #$id"))
}
}
package de.scrum_master.stackoverflow.q66208875
class UserService {
UserRepository userRepository = new UserRepository()
User getResponsible(Map configs, List<Map> agents) {
Integer responsibleId = configs.responsibleId as Integer
Optional<User> userOptional = userRepository.findById(responsibleId)
User user = userOptional.orElse(null)
user
}
}
package de.scrum_master.stackoverflow.q66208875
import spock.lang.Specification
class UserServiceTest extends Specification {
UserService userService
void setup() {
userService = new UserService()
userService.userRepository = Mock(UserRepository)
}
def "retrieve the responsible of interaction in JivoChat by configs of plugin item"() {
given: 'that exist a collection of JivoChat interaction configurations'
List<Map> agents = null
Map configs = [responsibleId: 1]
when: 'the main method is called'
User user = userService.getResponsible(configs, agents)
then: 'the method get last agent and search in DB by e-mail'
1 * userService.userRepository.findById(_) >> Optional.of(new User(username: "XPTO"))//.orElse("null")
}
}
看看我是如何在一行中结合存根方法结果和验证模拟交互的?
你也不需要任何GroovyMock(Optional)
,无论那是什么意思。您还需要确保获得findById(_)
正确的结果类型并删除 false .orElse("null")
。
推荐阅读
- java - 为什么像 java.net.InetAddress 这样的 Java 类不记录任何内容?
- c++ - glCopyPixels() 没有返回选定的缓冲区像素
- python - 如果存在数据框列值,则读取字典中的文件并返回文件值
- c - 将 char 与输入中的参数进行比较
- discord.py - 当用户对帖子做出反应时打印一些东西的不和谐机器人
- ios - iOS 14 唯一问题:键盘扩展中的图像不再显示(但在 iOS 13 中工作正常)
- php - PHP 或 MYSQL:批量编辑:result($_POST["keyword..and ID,放入新表,如果不存在,则跳过并继续
- python-3.x - Stack.peek() 返回正确的值,但函数说它不是
- javascript - LWC 对来自@wire 的 DIV 执行 querySelector
- entity-framework-core - 在其他模型上为多个导航属性重用外键