forked from mockk/mockk
/
StubbingAwaitingAnswerState.kt
75 lines (59 loc) · 2.5 KB
/
StubbingAwaitingAnswerState.kt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
package io.mockk.impl.recording.states
import io.mockk.*
import io.mockk.impl.log.Logger
import io.mockk.impl.recording.CommonCallRecorder
import io.mockk.impl.stub.AnswerAnsweringOpportunity
import io.mockk.impl.stub.MockKStub
class StubbingAwaitingAnswerState(recorder: CommonCallRecorder) : CallRecordingState(recorder) {
val log = recorder.safeToString(Logger<StubbingAwaitingAnswerState>())
override fun answerOpportunity(): MockKGateway.AnswerOpportunity<*> {
val calls = recorder.calls
var answerOpportunity: AnswerAnsweringOpportunity<*>? = null
for ((idx, recordedCall) in calls.withIndex()) {
val lastCall = idx == calls.size - 1
val ans = if (lastCall) {
answerOpportunity = AnswerAnsweringOpportunity<Any> {
recorder.safeExec { recordedCall.matcher.toString() }
}
answerOpportunity
} else if (recordedCall.isRetValueMock) {
ConstantAnswer(recordedCall.retValue)
} else {
continue
}
val mock = recordedCall.matcher.self
val stub = recorder.stubRepo.stubFor(mock)
stub.addAnswer(recordedCall.matcher, ans)
if (stub::class == MockKStub::class) {
assignFieldIfMockingProperty(mock, recordedCall.matcher, ans)
}
}
calls.clear()
log.trace { "Done stubbing. Still accepting additional answers" }
recorder.state = recorder.factories.answeringState(recorder)
return answerOpportunity!!
}
private fun assignFieldIfMockingProperty(mock: Any, matcher: InvocationMatcher, ans: Answer<Any?>) {
if (ans is AnswerAnsweringOpportunity<*>) {
ans.onFirstAnswer { answer ->
assignFieldIfMockingProperty(mock, matcher, answer)
}
return
}
try {
if (ans !is ConstantAnswer) {
return
}
val methodName = matcher.method.name
if (!methodName.startsWith("get")) {
return
}
val fieldName = methodName.substring("get".length)
.toCamelCase()
InternalPlatformDsl.dynamicSetField(mock, fieldName, ans.constantValue)
} catch (ex: Exception) {
log.warn(ex) { "Failed to set backing field (skipping)" }
}
}
private fun String.toCamelCase() = if (isEmpty()) this else substring(0, 1).lowercase() + substring(1)
}