如何对参数中的回调进行单元测试 - Kotlin
How to unit test a callback in parameter - Kotlin
我有一个客户端 class(在 Android 应用程序中用 Kotlin 编写)实现了一个接口 ReadyCallback
(在应用程序库中用 Java 编写) ,该应用程序依赖于此库)。在客户端中,我有一个 createClient()
方法,它将创建一个带有 ReadyCallback 参数的客户端。如果准备好了,我会通过调用classC.otherMethod()
来执行其他任务,如果没有准备好,我只是创建客户端而不做其他事情:
在图书馆:
// Somewhere in this library, I have logic to call `readyCallback.onReady()` when I consider it's "ready"
interface ReadyCallback {
void onReady()
}
class Manager {
private final ReadyCallback readyCallback;
public void onConnected(final boolean isConnected) {
if (isConnected) {
readyCallback.onReady();
}
}
}
在应用程序中:
class ClassA internal constructor(private val clientProvider: ClassB, private val classC: ClassC, private val classD: ClassD) : ReadyCallback {
fun createClient() {
val client = clientProvider.create(getReadyCallback())
}
private fun getReadyCallback() {
return ReadyCallback { onReady() }
}
override fun onReady() {
logInfo { "It's ready! Now do some stuff by calling classC.otherMethod()" }
classC.otherMethod()
}
}
在单元测试中,我想验证当我创建客户端并准备就绪时,classC 的 otherMethod() 将被调用。我尝试执行以下操作,但它不正确:
import com.nhaarman.mockitokotlin2.*
import org.junit.*
class ClassATest {
lateinit var unitUnderTest: ClassA
lateinit var clientProviderMock: ClassB
lateinit var classCMock: ClassC
lateinit var clientMock: ClassD
@Before
override fun setup() {
super.setup()
clientProviderMock = mock()
classCMock = mock()
clientMock = mock()
unitUnderTest = ClassA(clientProvider = clientProviderMock, classC = classCMock, classD = classDMock)
whenever(clientProviderMock.create(any()).thenReturn(client)
}
@Test
fun `when create client then call otherMethod`() {
unitUnderTest.createClient()
verify(classCMock).otherMethod()
}
}
错误信息显示:
Wanted but not invoked:
classC.otherMethod();
Actually, there were zero interactions with this mock.
我认为我收到此错误的原因是,如果我不调用 getReadyCallback()
,这意味着我没有调用回调,所以没有调用 classC.otherMethod()。但除此之外我真的坚持这一点,我不知道如何对我的欲望行为进行单元测试(如果准备好了, classC.otherMethod() 将被调用,如果没有准备好,这个方法将不会被调用).
我知道我不能做下面这样的事情,因为 unitUnderTest 不是模拟对象:
callbackMock = mock()
whenever(unitUnderTest.getReadyCallback()).thenReturn(callbackMock)
whenever(clientProviderMock.create(callbackMock).thenReturn(client)
有人可以帮我吗?
我能想到的唯一方法是在回调的 onReady()
方法中添加一个布尔标志。所以会变成:
图书馆中:
interface ReadyCallback {
void onReady(final boolean isReady)
}
class Manager {
private final ReadyCallback readyCallback;
public void onConnected(final boolean isConnected) {
if (isConnected) {
readyCallback.onReady(true);
} else {
readyCallback.onReady(false);
}
}
}
在应用程序中:
class ClassA internal constructor(private val clientProvider: ClassB, private val classC: ClassC, private val classD: ClassD) : ReadyCallback {
fun createClient() {
val client = clientProvider.create(getReadyCallback())
}
private fun getReadyCallback() {
return ReadyCallback { isReady -> onReady(isReady) }
}
override fun onReady(isReady: Boolean) {
if (isReady) {
logInfo { "It's ready! Now do some stuff by calling classC.otherMethod()" }
classC.otherMethod()
}
}
}
在单元测试中:
import com.nhaarman.mockitokotlin2.*
import org.junit.*
class ClassATest {
lateinit var unitUnderTest: ClassA
lateinit var clientProviderMock: ClassB
lateinit var classCMock: ClassC
lateinit var clientMock: ClassD
@Before
override fun setup() {
super.setup()
clientProviderMock = mock()
classCMock = mock()
clientMock = mock()
unitUnderTest = ClassA(clientProvider = clientProviderMock, classC = classCMock, classD = classDMock)
whenever(clientProviderMock.create(any()).thenReturn(client)
}
@Test
fun `when create client and ready then call otherMethod`() {
unitUnderTest.onReady(true)
unitUnderTest.createClient()
verify(classCMock).otherMethod()
}
@Test
fun `when create client and not ready then do not call otherMethod`() {
unitUnderTest.onReady(false)
unitUnderTest.createClient()
verifyZeroInteractions(classCMock)
}
}
但我仍然不知道如何在回调方法中没有布尔参数的情况下进行测试。有人知道怎么做吗?
我想我明白了。我不需要 onReady()
中的参数。
在图书馆:
interface ReadyCallback {
void onReady()
}
// place to determine when is "ready"
class Manager {
private final ReadyCallback readyCallback;
public void onConnected(final boolean isConnected) {
if (isConnected) {
readyCallback.onReady();
}
}
}
在应用程序中:
class ClassA internal constructor(private val clientProvider: ClassB, private val classC: ClassC, private val classD: ClassD) : ReadyCallback {
fun createClient() {
val client = clientProvider.create(getReadyCallback())
}
private fun getReadyCallback() {
return ReadyCallback { onReady() }
}
override fun onReady() {
logInfo { "It's ready! Now do some stuff by calling classC.otherMethod()" }
classC.otherMethod()
}
}
在单元测试中:
import com.nhaarman.mockitokotlin2.*
import org.junit.*
class ClassATest {
lateinit var unitUnderTest: ClassA
lateinit var clientProviderMock: ClassB
lateinit var classCMock: ClassC
lateinit var clientMock: ClassD
@Before
override fun setup() {
super.setup()
clientProviderMock = mock()
classCMock = mock()
clientMock = mock()
unitUnderTest = ClassA(clientProvider = clientProviderMock, classC = classCMock, classD = classDMock)
whenever(clientProviderMock.create(any()).thenReturn(client)
}
@Test
fun `when create client and ready then call otherMethod`() {
unitUnderTest.onReady()
unitUnderTest.createClient()
verify(classCMock).otherMethod()
}
@Test
fun `when create client and not ready then do not call otherMethod`() {
unitUnderTest.createClient()
verifyZeroInteractions(classCMock)
}
}
我有一个客户端 class(在 Android 应用程序中用 Kotlin 编写)实现了一个接口 ReadyCallback
(在应用程序库中用 Java 编写) ,该应用程序依赖于此库)。在客户端中,我有一个 createClient()
方法,它将创建一个带有 ReadyCallback 参数的客户端。如果准备好了,我会通过调用classC.otherMethod()
来执行其他任务,如果没有准备好,我只是创建客户端而不做其他事情:
在图书馆:
// Somewhere in this library, I have logic to call `readyCallback.onReady()` when I consider it's "ready"
interface ReadyCallback {
void onReady()
}
class Manager {
private final ReadyCallback readyCallback;
public void onConnected(final boolean isConnected) {
if (isConnected) {
readyCallback.onReady();
}
}
}
在应用程序中:
class ClassA internal constructor(private val clientProvider: ClassB, private val classC: ClassC, private val classD: ClassD) : ReadyCallback {
fun createClient() {
val client = clientProvider.create(getReadyCallback())
}
private fun getReadyCallback() {
return ReadyCallback { onReady() }
}
override fun onReady() {
logInfo { "It's ready! Now do some stuff by calling classC.otherMethod()" }
classC.otherMethod()
}
}
在单元测试中,我想验证当我创建客户端并准备就绪时,classC 的 otherMethod() 将被调用。我尝试执行以下操作,但它不正确:
import com.nhaarman.mockitokotlin2.*
import org.junit.*
class ClassATest {
lateinit var unitUnderTest: ClassA
lateinit var clientProviderMock: ClassB
lateinit var classCMock: ClassC
lateinit var clientMock: ClassD
@Before
override fun setup() {
super.setup()
clientProviderMock = mock()
classCMock = mock()
clientMock = mock()
unitUnderTest = ClassA(clientProvider = clientProviderMock, classC = classCMock, classD = classDMock)
whenever(clientProviderMock.create(any()).thenReturn(client)
}
@Test
fun `when create client then call otherMethod`() {
unitUnderTest.createClient()
verify(classCMock).otherMethod()
}
}
错误信息显示:
Wanted but not invoked:
classC.otherMethod();
Actually, there were zero interactions with this mock.
我认为我收到此错误的原因是,如果我不调用 getReadyCallback()
,这意味着我没有调用回调,所以没有调用 classC.otherMethod()。但除此之外我真的坚持这一点,我不知道如何对我的欲望行为进行单元测试(如果准备好了, classC.otherMethod() 将被调用,如果没有准备好,这个方法将不会被调用).
我知道我不能做下面这样的事情,因为 unitUnderTest 不是模拟对象:
callbackMock = mock()
whenever(unitUnderTest.getReadyCallback()).thenReturn(callbackMock)
whenever(clientProviderMock.create(callbackMock).thenReturn(client)
有人可以帮我吗?
我能想到的唯一方法是在回调的 onReady()
方法中添加一个布尔标志。所以会变成:
图书馆中:
interface ReadyCallback {
void onReady(final boolean isReady)
}
class Manager {
private final ReadyCallback readyCallback;
public void onConnected(final boolean isConnected) {
if (isConnected) {
readyCallback.onReady(true);
} else {
readyCallback.onReady(false);
}
}
}
在应用程序中:
class ClassA internal constructor(private val clientProvider: ClassB, private val classC: ClassC, private val classD: ClassD) : ReadyCallback {
fun createClient() {
val client = clientProvider.create(getReadyCallback())
}
private fun getReadyCallback() {
return ReadyCallback { isReady -> onReady(isReady) }
}
override fun onReady(isReady: Boolean) {
if (isReady) {
logInfo { "It's ready! Now do some stuff by calling classC.otherMethod()" }
classC.otherMethod()
}
}
}
在单元测试中:
import com.nhaarman.mockitokotlin2.*
import org.junit.*
class ClassATest {
lateinit var unitUnderTest: ClassA
lateinit var clientProviderMock: ClassB
lateinit var classCMock: ClassC
lateinit var clientMock: ClassD
@Before
override fun setup() {
super.setup()
clientProviderMock = mock()
classCMock = mock()
clientMock = mock()
unitUnderTest = ClassA(clientProvider = clientProviderMock, classC = classCMock, classD = classDMock)
whenever(clientProviderMock.create(any()).thenReturn(client)
}
@Test
fun `when create client and ready then call otherMethod`() {
unitUnderTest.onReady(true)
unitUnderTest.createClient()
verify(classCMock).otherMethod()
}
@Test
fun `when create client and not ready then do not call otherMethod`() {
unitUnderTest.onReady(false)
unitUnderTest.createClient()
verifyZeroInteractions(classCMock)
}
}
但我仍然不知道如何在回调方法中没有布尔参数的情况下进行测试。有人知道怎么做吗?
我想我明白了。我不需要 onReady()
中的参数。
在图书馆:
interface ReadyCallback {
void onReady()
}
// place to determine when is "ready"
class Manager {
private final ReadyCallback readyCallback;
public void onConnected(final boolean isConnected) {
if (isConnected) {
readyCallback.onReady();
}
}
}
在应用程序中:
class ClassA internal constructor(private val clientProvider: ClassB, private val classC: ClassC, private val classD: ClassD) : ReadyCallback {
fun createClient() {
val client = clientProvider.create(getReadyCallback())
}
private fun getReadyCallback() {
return ReadyCallback { onReady() }
}
override fun onReady() {
logInfo { "It's ready! Now do some stuff by calling classC.otherMethod()" }
classC.otherMethod()
}
}
在单元测试中:
import com.nhaarman.mockitokotlin2.*
import org.junit.*
class ClassATest {
lateinit var unitUnderTest: ClassA
lateinit var clientProviderMock: ClassB
lateinit var classCMock: ClassC
lateinit var clientMock: ClassD
@Before
override fun setup() {
super.setup()
clientProviderMock = mock()
classCMock = mock()
clientMock = mock()
unitUnderTest = ClassA(clientProvider = clientProviderMock, classC = classCMock, classD = classDMock)
whenever(clientProviderMock.create(any()).thenReturn(client)
}
@Test
fun `when create client and ready then call otherMethod`() {
unitUnderTest.onReady()
unitUnderTest.createClient()
verify(classCMock).otherMethod()
}
@Test
fun `when create client and not ready then do not call otherMethod`() {
unitUnderTest.createClient()
verifyZeroInteractions(classCMock)
}
}