gpt4 book ai didi

安卓。 Mockito 使用真实对象而不是模拟对象

转载 作者:行者123 更新时间:2023-11-28 20:28:19 25 4
gpt4 key购买 nike

所以,我只是在编写简单的测试。问题是测试运行器运行真正的“存储库”类代码而不是模拟代码......您知道为什么我可以在这方面获得异常(exception)吗?

测试类

class SingInFacebookPresenterTest {

@Mock
private lateinit var view: SignInFacebookContract.View

@Mock
private lateinit var repository: Repository

@Captor
private lateinit var callback: ArgumentCaptor<RepositoryCallback.FacebookLoginImp>

private lateinit var presenter: SingInFacebookPresenter

private val serverToken = "token"

@Before
fun init() {

MockitoAnnotations.initMocks(this)

presenter = SingInFacebookPresenter(MockContext(), repository, view)
}

@Test
fun facebook_login_success() {

//Given
val token = "token"
val serverToken = "server token"

presenter.loginViaFacebook(token)

//When
verify(repository).loginViaFacebook(token, callback.capture())


callback.value.onSuccess(serverToken)

//Then
verify(view).success(serverToken)
}

主持人

class SingInFacebookPresenter(var context: Context, var repository: Repository, var view: SignInFacebookContract.View): SignInFacebookContract.Presenter {

public override fun loginViaFacebook(token: String) {
repository.loginViaFacebook(token, object : RepositoryCallback.FacebookLoginImp {
override fun onSuccess(token: String) {
view.success(token)
}

override fun onFailure() {
view.onFailure()
}

})
}

存储库

open class Repository(context: Context) {

init {
ApiHelper(context)
}

private var facebookLoginPresenterCallback: RepositoryCallback.FacebookLoginImp? = null

fun loginViaFacebook(token: String, facebookLoginPresenterCallback: RepositoryCallback.FacebookLoginImp?) {
// this.facebookLoginPresenterCallback = facebookLoginPresenterCallback
val signInResponse = ApiHelper.signInViaFacebook(token)
// signInResponse.enqueue(signInFacebookCallback)
signInResponse.enqueue(object : Callback<SignInResponse> {
override fun onResponse(call: Call<SignInResponse>?, response: Response<SignInResponse>?) {
if (response!!.isSuccessful) {
val token = response.body()?.token ?: return
facebookLoginPresenterCallback?.onSuccess(token)
return
}
facebookLoginPresenterCallback?.onFailure()
}

override fun onFailure(call: Call<SignInResponse>?, t: Throwable?) {
facebookLoginPresenterCallback?.onFailure()
}
})
}

private val signInFacebookCallback = object : Callback<SignInResponse> {
override fun onResponse(call: Call<SignInResponse>?, response: Response<SignInResponse>?) {
if (response!!.isSuccessful) {
val token = response.body()?.token ?: return
facebookLoginPresenterCallback?.onSuccess(token)
return
}
facebookLoginPresenterCallback?.onFailure()
}

override fun onFailure(call: Call<SignInResponse>?, t: Throwable?) {
facebookLoginPresenterCallback?.onFailure()
}
}
}

异常(exception):

Exception in thread "OkHttp Dispatcher" java.lang.NoSuchMethodError: okhttp3.internal.Platform.log(Ljava/lang/String;)V
at okhttp3.logging.HttpLoggingInterceptor$Logger$1.log(HttpLoggingInterceptor.java:109)
at okhttp3.logging.HttpLoggingInterceptor.intercept(HttpLoggingInterceptor.java:157)
at okhttp3.RealCall$ApplicationInterceptorChain.proceed(RealCall.java:190)
at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:163)
at okhttp3.RealCall.access$100(RealCall.java:30)
at okhttp3.RealCall$AsyncCall.execute(RealCall.java:127)
at okhttp3.internal.NamedRunnable.run(NamedRunnable.java:32)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
Exception in thread "OkHttp Dispatcher" java.lang.NoSuchMethodError: okhttp3.internal.Platform.log(Ljava/lang/String;)V
at okhttp3.logging.HttpLoggingInterceptor$Logger$1.log(HttpLoggingInterceptor.java:109)
at okhttp3.logging.HttpLoggingInterceptor.intercept(HttpLoggingInterceptor.java:157)
at okhttp3.RealCall$ApplicationInterceptorChain.proceed(RealCall.java:190)
at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:163)
at okhttp3.RealCall.access$100(RealCall.java:30)
at okhttp3.RealCall$AsyncCall.execute(RealCall.java:127)
at okhttp3.internal.NamedRunnable.run(NamedRunnable.java:32)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)

org.mockito.exceptions.base.MockitoException:
No argument value was captured!
You might have forgotten to use argument.capture() in verify()...
...or you used capture() in stubbing but stubbed method was not called.
Be aware that it is recommended to use capture() only with verify()

Examples of correct argument capturing:
ArgumentCaptor<Person> argument = ArgumentCaptor.forClass(Person.class);
verify(mock).doSomething(argument.capture());
assertEquals("John", argument.getValue().getName());

最佳答案

好吧,这是一个很好的。这是我发现的:

测试代码不是问题,Mockito 出于某种原因创建了 Repository 的真实(?)实例。或者至少无法在某处拦截方法调用?

无论如何,这是一个完全精简的示例,它重现了 org.mockito:mockito-core:2.7.11 的问题:

open class Greeter {
fun hello() = "hello world"
}

class MockitoJavaExample {

@Test
fun test() {
val greeter: Greeter = mock()
println(greeter.hello()) // prints "hello world" which it shouldn't
}

}

我对 Mockito 的内部结构不够熟悉,无法告诉您这是如何发生的,但是切换到使用 mockito-inline,一种不同的模拟方法解决了这个问题。它还使您能够在 Kotlin 中模拟非 open 类,无论如何您可能都想要这样,这样您就不必为了测试而打开类进行扩展。使用此方法,无论类是否打开,您都可以正确地获得函数返回的 null,因此它不使用真正的实现。

您可以使用 compile 'org.mockito:mockito-inline:2.7.11' 而不是 -core 版本切换到 Mockito 的内联版本。

关于安卓。 Mockito 使用真实对象而不是模拟对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42767781/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com