Spock单元测试使用spring数据导致可选错误



我开始在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手册章节"结合嘲笑和存根"中找到:

注意:相同方法调用的模拟和存根必须发生在相同的交互中。

所以解是这样的:

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(_)结果类型,并删除错误的.orElse("null")

最新更新