如何在 Groovy/Grails Spoc 中模拟 SQL 调用
How to mock an SQL call in Groovy/Grails Spoc
我有一个服务class写在groovy,如下:
import groovy.sql.Sql
import javax.sql.DataSource
import java.sql.SQLException
class DatabaseService {
DataSource dataSource;
void registerUser(User user) {
try {
def sql = new Sql(dataSource);
sql.call("{call regUser(?)}", [user.name])
} catch (SQLException e) {
log.error("unable to register the user", e)
throw e;
}
}
}
我想在这里做的是模拟 sql.call 方法,抛出一个 SQLException。编写集成测试来执行此操作目前是不可能的。
这是我目前的情况:
void "test registerDeveloper exception handling"() {
String expectedErrorMsg = "exception from test"
DataSource mockedSource = Mock(DataSource)
User user = new User(name: "joe")
Sql mockedSql = Mock(Sql)
DatabaseService databaseService = new DatabaseService(dataSource:mockedSource)
given:
mockedSql.call(_,_) << {throw new SQLException()}
when:
databaseService.registerUser(user)
then:
def exception = thrown(SQLException)
exception.message == expectedErrorMsg
}
使用上面的代码,我得到这个错误:
groovy.lang.MissingMethodException:没有方法签名:java.lang.Integer.leftShift() 适用于参数类型:(UcopRip.DatabaseServiceSpec$__spock_feature_0_0_closure1) 值:[UcopRip.DatabaseServiceSpec $__spock_feature_0_0_closure1@77049094]
可能的解决方案:leftShift(java.lang.Number), rightShift(java.lang.Number)
如果我将 << 更改为 >>,我会收到此错误:
类型 'java.sql.SQLException' 的预期异常,但得到 'java.lang.NullPointerException',指向数据库服务 class 中的 sql.call 行。
有人知道我做错了什么吗?我当然不熟悉使用 SPOCK 进行测试,但似乎无法在网上找到人们嘲笑 SQL 方法的任何地方。
交互应在 when 子句中,并使用 >>
此外 'Sql' 是一个 class,并且是在您的服务中创建的:您不能很容易地模拟它。使用像 hsqldb 这样的内存数据库来测试这种东西更简单,但是你可以模拟连接和准备语句(它很丑)
void "test registerDeveloper exception handling"() {
given:
String expectedErrorMsg = "exception from test"
DataSource mockedSource = Mock(DataSource)
def user = new User(name: "joe")
def databaseService = new DatabaseService(dataSource:mockedSource)
when:
databaseService.registerUser(user)
then:
1* mockedSource.getConnection() >> {throw new SQLException(expectedErrorMsg)}
and:
def exception = thrown(SQLException)
exception.message == expectedErrorMsg
}
我有一个服务class写在groovy,如下:
import groovy.sql.Sql
import javax.sql.DataSource
import java.sql.SQLException
class DatabaseService {
DataSource dataSource;
void registerUser(User user) {
try {
def sql = new Sql(dataSource);
sql.call("{call regUser(?)}", [user.name])
} catch (SQLException e) {
log.error("unable to register the user", e)
throw e;
}
}
}
我想在这里做的是模拟 sql.call 方法,抛出一个 SQLException。编写集成测试来执行此操作目前是不可能的。
这是我目前的情况:
void "test registerDeveloper exception handling"() {
String expectedErrorMsg = "exception from test"
DataSource mockedSource = Mock(DataSource)
User user = new User(name: "joe")
Sql mockedSql = Mock(Sql)
DatabaseService databaseService = new DatabaseService(dataSource:mockedSource)
given:
mockedSql.call(_,_) << {throw new SQLException()}
when:
databaseService.registerUser(user)
then:
def exception = thrown(SQLException)
exception.message == expectedErrorMsg
}
使用上面的代码,我得到这个错误:
groovy.lang.MissingMethodException:没有方法签名:java.lang.Integer.leftShift() 适用于参数类型:(UcopRip.DatabaseServiceSpec$__spock_feature_0_0_closure1) 值:[UcopRip.DatabaseServiceSpec $__spock_feature_0_0_closure1@77049094] 可能的解决方案:leftShift(java.lang.Number), rightShift(java.lang.Number)
如果我将 << 更改为 >>,我会收到此错误: 类型 'java.sql.SQLException' 的预期异常,但得到 'java.lang.NullPointerException',指向数据库服务 class 中的 sql.call 行。
有人知道我做错了什么吗?我当然不熟悉使用 SPOCK 进行测试,但似乎无法在网上找到人们嘲笑 SQL 方法的任何地方。
交互应在 when 子句中,并使用 >>
此外 'Sql' 是一个 class,并且是在您的服务中创建的:您不能很容易地模拟它。使用像 hsqldb 这样的内存数据库来测试这种东西更简单,但是你可以模拟连接和准备语句(它很丑)
void "test registerDeveloper exception handling"() {
given:
String expectedErrorMsg = "exception from test"
DataSource mockedSource = Mock(DataSource)
def user = new User(name: "joe")
def databaseService = new DatabaseService(dataSource:mockedSource)
when:
databaseService.registerUser(user)
then:
1* mockedSource.getConnection() >> {throw new SQLException(expectedErrorMsg)}
and:
def exception = thrown(SQLException)
exception.message == expectedErrorMsg
}