如何验证被测 class 内的交互?
How to verify interactions within the class under test?
// class under specification
public class TeamService {
// method under specification
public void deleteTeam(String id) {
/* some other calls */
this.moveAssets(team) // calls method within the class under spec.
}
// I would like to stub / mock this method
public void moveAssets(Team team){
// logic
}
}
Spock 规格
def deleteTeam(){
given:
TeamService teamService = new TeamService()
when: 'I delete the team'
teamService.deleteTeam()
then: 'I want to check that moveAssets gets called(team resources going to be preserved
and that deleteTeam (external class that deletes the team) gets called (has no issues here)'
1 * teamService.moveAssets(id) >> {} //See Q1
/*
Q1: I want to test that this call is made
but currently it does not count as interaction for some reason so I get an error.
From what I read you can't stub the calls unless the class is mocked -
but here I do have an important need to check on the method within the class under specification
(that is not mocked). What are my options?
I know I can in theory move moveAssets to some other class,
which I can then mock and accomplish it but that does not feel right.
*/
}
因此在 Spock 的规范中 class,TeamService 是规范中的 class,deleteTeam 是规范中的方法。
问题
我收到 moveAssets 方法的错误 0 调用。
我希望能够对 moveAssets 方法进行存根/测试,但关于如何实现该方法的信息并不多。
我不想将 moveAssets 重新定位到另一个类(这样我就可以模拟它)。
任何指导表示赞赏。
必须有一些更好的方法来处理这种情况。
总结:
如何测试从 'Method Under Specification (teamServices.deleteTeam())' 调用的 'Class Under Specification' teamServices.moveAssets()) 方法?
正如您已经注意到的那样,您只能检查模拟对象类型(即模拟、存根或间谍)的交互。后者,spy,是您在这种情况下所需要的,例如:
TeamService teamService =
Spy(constructorArgs: [mockedInjectedService1, mockedInjectedService2])
这是一个MCVE:
package de.scrum_master.Whosebug.q67950174
class Team {
String id
}
package de.scrum_master.Whosebug.q67950174
class TeamService {
def dep1, dep2
TeamService(dep1, dep2) {
this.dep1 = dep1
this.dep2 = dep2
}
boolean moveAssets(Team team) {
println "Moving assets for team $team"
return false
}
void deleteTeam(String id) {
Team team = findTeamById(id)
moveAssets(team)
delete(team)
}
Team findTeamById(String id) {
println "Searching for team $team"
return new Team(id: id)
}
void delete(Team team) {
println "Deleting team $team"
}
}
package de.scrum_master.Whosebug.q67950174
import spock.lang.Specification
class TeamServiceTest extends Specification {
def deleteTeam() {
given:
Team teamDocument = new Team(id: "dummy")
String id = "foo"
def mockedInjectedService1 = "X"
def mockedInjectedService2 = "Y"
TeamService teamService = Spy(constructorArgs: [mockedInjectedService1, mockedInjectedService2])
when: 'I delete the team'
teamService.deleteTeam(id)
then: 'I want to check that moveAssets gets called(team resources going to be preserved'
1 * teamService.findTeamById(id) >> teamDocument
1 * teamService.moveAssets(teamDocument) >> true
}
}
// class under specification
public class TeamService {
// method under specification
public void deleteTeam(String id) {
/* some other calls */
this.moveAssets(team) // calls method within the class under spec.
}
// I would like to stub / mock this method
public void moveAssets(Team team){
// logic
}
}
Spock 规格
def deleteTeam(){
given:
TeamService teamService = new TeamService()
when: 'I delete the team'
teamService.deleteTeam()
then: 'I want to check that moveAssets gets called(team resources going to be preserved
and that deleteTeam (external class that deletes the team) gets called (has no issues here)'
1 * teamService.moveAssets(id) >> {} //See Q1
/*
Q1: I want to test that this call is made
but currently it does not count as interaction for some reason so I get an error.
From what I read you can't stub the calls unless the class is mocked -
but here I do have an important need to check on the method within the class under specification
(that is not mocked). What are my options?
I know I can in theory move moveAssets to some other class,
which I can then mock and accomplish it but that does not feel right.
*/
}
因此在 Spock 的规范中 class,TeamService 是规范中的 class,deleteTeam 是规范中的方法。
问题 我收到 moveAssets 方法的错误 0 调用。 我希望能够对 moveAssets 方法进行存根/测试,但关于如何实现该方法的信息并不多。 我不想将 moveAssets 重新定位到另一个类(这样我就可以模拟它)。 任何指导表示赞赏。
必须有一些更好的方法来处理这种情况。
总结:
如何测试从 'Method Under Specification (teamServices.deleteTeam())' 调用的 'Class Under Specification' teamServices.moveAssets()) 方法?
正如您已经注意到的那样,您只能检查模拟对象类型(即模拟、存根或间谍)的交互。后者,spy,是您在这种情况下所需要的,例如:
TeamService teamService =
Spy(constructorArgs: [mockedInjectedService1, mockedInjectedService2])
这是一个MCVE:
package de.scrum_master.Whosebug.q67950174
class Team {
String id
}
package de.scrum_master.Whosebug.q67950174
class TeamService {
def dep1, dep2
TeamService(dep1, dep2) {
this.dep1 = dep1
this.dep2 = dep2
}
boolean moveAssets(Team team) {
println "Moving assets for team $team"
return false
}
void deleteTeam(String id) {
Team team = findTeamById(id)
moveAssets(team)
delete(team)
}
Team findTeamById(String id) {
println "Searching for team $team"
return new Team(id: id)
}
void delete(Team team) {
println "Deleting team $team"
}
}
package de.scrum_master.Whosebug.q67950174
import spock.lang.Specification
class TeamServiceTest extends Specification {
def deleteTeam() {
given:
Team teamDocument = new Team(id: "dummy")
String id = "foo"
def mockedInjectedService1 = "X"
def mockedInjectedService2 = "Y"
TeamService teamService = Spy(constructorArgs: [mockedInjectedService1, mockedInjectedService2])
when: 'I delete the team'
teamService.deleteTeam(id)
then: 'I want to check that moveAssets gets called(team resources going to be preserved'
1 * teamService.findTeamById(id) >> teamDocument
1 * teamService.moveAssets(teamDocument) >> true
}
}