如何通过模拟其方法正在使用的外部依赖来测试对象表达式方法?
How To Test Object expression methods by mocking external dependency which its mothod is using?
在编写单元测试时,@InjectMock
创建了 class 的实例并注入使用 @Mock
.[= 定义的模拟实例14=]
所以当我们测试 class 的方法时,这工作正常。 我在测试对象表达式的方法时遇到问题。
例如:
我有一个对象 class DbService.
object DbService {
private lateinit var connection: Connection
init {
makeConnection()
}
private fun makeConnection(){
Class.forName("com.mysql.cj.jdbc.Driver")
try{
connection = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/Users", "user", "password")
}catch (ex: Exception){
println(ex)
}
}
fun checkConnection(){
var preparedStatement: PreparedStatement = connection.prepareStatement("SHOW DATABASES;")
var resultSet = preparedStatement.executeQuery()
while(resultSet.next()){
println(resultSet.getObject(1))
}
}
}
现在我必须测试 checkConnection
功能。我该怎么做?
实际上做了更多的研究,我得到了一些提示并且对我有用。
就像,您可以使用 setter 方法进行手动依赖注入。
setter-based Dependency Injection
所以我做了什么,我又添加了一个函数来像这样手动设置连接对象。
object DbService {
private lateinit var connection: Connection
init {
makeConnection()
}
private fun makeConnection(){
Class.forName("com.mysql.cj.jdbc.Driver")
try{
connection = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/Users", "user", "password")
}catch (ex: Exception){
println(ex)
}
}
// setter based dependency injection <----
fun initializeConnectionObject(conn: Connection){
connection = conn
}
fun printingSomeMoreData(){
var statement: Statement
var resultSet: ResultSet
var preparedStatement: PreparedStatement = connection.prepareStatement("SELECT * FROM titles where title=?;")
preparedStatement.setString(1, "Engineer")
resultSet = preparedStatement.executeQuery()
val columnCount = resultSet.metaData.columnCount
while(resultSet.next()){
for(i in 1..columnCount){
print(resultSet.getObject(i).toString() + " ")
}
println()
}
}
}
测试如下:
@RunWith(MockitoJUnitRunner::class)
class DbServiceTest {
private lateinit var dbService: DbService
@Mock lateinit var mockedConnection: Connection
@Mock lateinit var mockedPreparedStatement: PreparedStatement
@Mock lateinit var mockedResultSet: ResultSet
@Mock
lateinit var mockedResultSetMetaData: ResultSetMetaData
@Before
fun setUp(){
MockitoAnnotations.initMocks(true)
}
@Test
fun printingSomeMoreDataTest() {
dbService = DbService
Mockito.`when`(mockedResultSetMetaData.columnCount).thenReturn(3)
Mockito.`when`(mockedResultSet.next()).thenReturn(true, true, true, true, false)
Mockito.`when`(mockedResultSet.metaData).thenReturn(mockedResultSetMetaData)
Mockito.`when`(mockedResultSet.getObject(1)).thenReturn("11", "21", "31", "41")
Mockito.`when`(mockedResultSet.getObject(2)).thenReturn("12", "22", "32", "42")
Mockito.`when`(mockedResultSet.getObject(3)).thenReturn("13", "23", "33", "43")
Mockito.`when`(mockedPreparedStatement.executeQuery()).thenReturn(mockedResultSet)
Mockito.`when`(mockedConnection.prepareStatement(Mockito.anyString())).thenReturn(mockedPreparedStatement)
dbService.initializeConnectionObject(mockedConnection) // <----
dbService.printingSomeMoreData()
Mockito.verify(mockedResultSet, times(12)).getObject(anyInt())
}
}
在编写单元测试时,@InjectMock
创建了 class 的实例并注入使用 @Mock
.[= 定义的模拟实例14=]
所以当我们测试 class 的方法时,这工作正常。 我在测试对象表达式的方法时遇到问题。
例如: 我有一个对象 class DbService.
object DbService {
private lateinit var connection: Connection
init {
makeConnection()
}
private fun makeConnection(){
Class.forName("com.mysql.cj.jdbc.Driver")
try{
connection = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/Users", "user", "password")
}catch (ex: Exception){
println(ex)
}
}
fun checkConnection(){
var preparedStatement: PreparedStatement = connection.prepareStatement("SHOW DATABASES;")
var resultSet = preparedStatement.executeQuery()
while(resultSet.next()){
println(resultSet.getObject(1))
}
}
}
现在我必须测试 checkConnection
功能。我该怎么做?
实际上做了更多的研究,我得到了一些提示并且对我有用。
就像,您可以使用 setter 方法进行手动依赖注入。
setter-based Dependency Injection
所以我做了什么,我又添加了一个函数来像这样手动设置连接对象。
object DbService {
private lateinit var connection: Connection
init {
makeConnection()
}
private fun makeConnection(){
Class.forName("com.mysql.cj.jdbc.Driver")
try{
connection = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/Users", "user", "password")
}catch (ex: Exception){
println(ex)
}
}
// setter based dependency injection <----
fun initializeConnectionObject(conn: Connection){
connection = conn
}
fun printingSomeMoreData(){
var statement: Statement
var resultSet: ResultSet
var preparedStatement: PreparedStatement = connection.prepareStatement("SELECT * FROM titles where title=?;")
preparedStatement.setString(1, "Engineer")
resultSet = preparedStatement.executeQuery()
val columnCount = resultSet.metaData.columnCount
while(resultSet.next()){
for(i in 1..columnCount){
print(resultSet.getObject(i).toString() + " ")
}
println()
}
}
}
测试如下:
@RunWith(MockitoJUnitRunner::class)
class DbServiceTest {
private lateinit var dbService: DbService
@Mock lateinit var mockedConnection: Connection
@Mock lateinit var mockedPreparedStatement: PreparedStatement
@Mock lateinit var mockedResultSet: ResultSet
@Mock
lateinit var mockedResultSetMetaData: ResultSetMetaData
@Before
fun setUp(){
MockitoAnnotations.initMocks(true)
}
@Test
fun printingSomeMoreDataTest() {
dbService = DbService
Mockito.`when`(mockedResultSetMetaData.columnCount).thenReturn(3)
Mockito.`when`(mockedResultSet.next()).thenReturn(true, true, true, true, false)
Mockito.`when`(mockedResultSet.metaData).thenReturn(mockedResultSetMetaData)
Mockito.`when`(mockedResultSet.getObject(1)).thenReturn("11", "21", "31", "41")
Mockito.`when`(mockedResultSet.getObject(2)).thenReturn("12", "22", "32", "42")
Mockito.`when`(mockedResultSet.getObject(3)).thenReturn("13", "23", "33", "43")
Mockito.`when`(mockedPreparedStatement.executeQuery()).thenReturn(mockedResultSet)
Mockito.`when`(mockedConnection.prepareStatement(Mockito.anyString())).thenReturn(mockedPreparedStatement)
dbService.initializeConnectionObject(mockedConnection) // <----
dbService.printingSomeMoreData()
Mockito.verify(mockedResultSet, times(12)).getObject(anyInt())
}
}