Kotlin test expected SingletonMap but was LinkedHashMap - unit-testing

I am new to Kotlin and Java so bear with me but I just wrote a Kotlin test as follows:
package com.squareup.cash.transactiongraph.service.actions
import com.squareup.cash.transactiongraph.TransactionGraphTestingModule
import com.squareup.cash.transactiongraph.client.franklin.FakeFranklinClient
import com.squareup.cash.transactiongraph.dataloader.DataLoaderRegistryFactory
import com.squareup.cash.transactiongraph.graphql.GraphQLContextFactory
import com.squareup.cash.transactiongraph.graphql.TransactionGraphContextFactory
import com.squareup.cash.transactiongraph.service.TransactionGraphGraphqlModule
import com.squareup.graphql.dataloaders.FlowDataLoaderDispatcher
import kotlinx.coroutines.future.await
import kotlinx.coroutines.runBlocking
import misk.testing.MiskTest
import misk.testing.MiskTestModule
import okhttp3.Headers
import org.junit.jupiter.api.Test
import org.assertj.core.api.Assertions.assertThat
#MiskTest(startService = true)
class CashCustomerTransactionsQueryTest {
#MiskTestModule
private val module = TransactionGraphTestingModule()
#Test
fun `returns an array of CashTransactions`() = runBlocking<Unit> {
val query = """
{
cashCustomerTransactions(customerToken: "customerToken") {
id
reasonCode
createdAt
}
}
""".trimIndent()
val result = execute(query)
assertThat(result["errors"]).isNull()
assertThat(result["data"]).isEqualTo(
mapOf(
"cashCustomerTransactions" to arrayOf(
mapOf(
"createdAt" to "2019-03-20T18:26:18Z",
"id" to "TOKEN",
"reasonCode" to "CARD_PRESENT_PURCHASE"
)
)
)
)
}
private suspend fun execute(query: String): Map<String, Any> {
val franklinClient = FakeFranklinClient()
val dataLoaderRegistryFactory = DataLoaderRegistryFactory()
val flowDataLoaderDispatcher = FlowDataLoaderDispatcher(dataLoaderRegistryFactory)
return flowDataLoaderDispatcher.run { registry ->
val contextFactory: GraphQLContextFactory =
TransactionGraphContextFactory(franklinClient)
TransactionGraphGraphqlModule().graphQL().executeAsync {
it
.query(query)
.context(contextFactory.build(Headers.Builder().build(), registry))
}.await().toSpecification()
}
}
}
Upon running the test it fails with the following error: expected: "{"cashCustomerTransactions"=[{"createdAt"="2019-03-20T18:26:18Z", "id"="TOKEN", "reasonCode"="CARD_PRESENT_PURCHASE"}]} (SingletonMap#58303289)" but was: "{"cashCustomerTransactions"=[{"createdAt"="2019-03-20T18:26:18Z", "id"="TOKEN", "reasonCode"="CARD_PRESENT_PURCHASE"}]} (LinkedHashMap#c32f16d)"
The following responses appear to be identical with the exception that one is a SingletonMap and one is a LinkedHashMap. I do not understand why the types are different. What am I doing incorrectly? Can someone please point me in the right direction. Thank you

Change arrayOf to listOf and the problem will be solved.

Related

TapKey Mobile SDK can't find a lock

I am developing a app in flutter and I am having a problem with detecting a locks via tapkey mobile sdk. I am login users with Token Exchange method, I have created new Identity Providers. I am creating a new user via a cloud function (Owners/{ownerAccountId}/IdentityProviders/{ipId}/Users however i'm not adding the contact) using the Client Credentials that i have also added to my.tapkey.com as new user and assigned a lock to it.
I can successfully run logInAsync with the token i am receiving via Token Exchange however when i try to find a nearby locks i got {} as a response (i will mention that the lock is next to me).
my code:
import android.Manifest
import android.content.pm.PackageManager
import androidx.core.app.ActivityCompat
import com.tapkey.mobile.TapkeyAppContext
import com.tapkey.mobile.TapkeyEnvironmentConfigBuilder
import com.tapkey.mobile.TapkeyServiceFactory
import com.tapkey.mobile.TapkeyServiceFactoryBuilder
import com.tapkey.mobile.ble.BleLockScanner
import com.tapkey.mobile.concurrent.CancellationToken
import com.tapkey.mobile.concurrent.CancellationTokenSource
import com.tapkey.mobile.manager.UserManager
import io.flutter.app.FlutterApplication
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.embedding.engine.FlutterEngineCache
import io.flutter.embedding.engine.dart.DartExecutor
import net.tpky.mc.time.ServerClock
import org.json.JSONObject
import java.net.HttpURLConnection
import java.net.URL
class TapKeyTest : FlutterApplication(), TapkeyAppContext {
private lateinit var tapkeyServiceFactory: TapkeyServiceFactory
lateinit var flutterEngine: FlutterEngine
companion object {
const val FLUTTER_ENGINE_NAME = "nps_flutter_engine_name"
}
override fun onCreate() {
super.onCreate()
flutterEngine = FlutterEngine(this)
flutterEngine.dartExecutor.executeDartEntrypoint(
DartExecutor.DartEntrypoint.createDefault()
)
FlutterEngineCache
.getInstance()
.put(FLUTTER_ENGINE_NAME, flutterEngine)
val serverClock = ServerClock()
val config = TapkeyEnvironmentConfigBuilder()
config.setBaseUri("https://my.tapkey.com/")
val b = TapkeyServiceFactoryBuilder(this )
.setServerClock(serverClock)
.setConfig(config.build())
val sf = b.build()
tapkeyServiceFactory = sf
}
override fun getTapkeyServiceFactory(): TapkeyServiceFactory {
return tapkeyServiceFactory
}
fun login(SECRET_TOKEN: String) {
val src = CancellationTokenSource()
val ct: CancellationToken = src.token
val userManager: UserManager = tapkeyServiceFactory.userManager
userManager.logInAsync(SECRET_TOKEN, ct)
.continueOnUi { userId -> scanLocks()}
.catchOnUi { asyncError -> println(asyncError.cause) } }
private fun scanLocks( ) {
if (ActivityCompat.checkSelfPermission(
this,
Manifest.permission.BLUETOOTH_SCAN
) != PackageManager.PERMISSION_GRANTED || ActivityCompat.checkSelfPermission(
this,
Manifest.permission.BLUETOOTH_CONNECT
) != PackageManager.PERMISSION_GRANTED
) {
return
} else {
tapkeyServiceFactory.bleLockScanner.locksChangedObservable
.addObserver { locks -> println(locks)}
println( tapkeyServiceFactory.bleLockScanner.locks)
println("Permission granted")
}
}
}
Is there a step that i have missed? Also i can't find anywhere new users that i am creating.
It seems, that you don't start the scanning:
BleLockScanner scanner = tapkeyServiceFactory.getBleLockScanner();
bleScanObserverRegistration = scanner.startForegroundScan();

Why is Koin scoping feature not working properly?

So scoping with Koin DI seem to throw a weird exception when KoinApplication::checkModules() method is called within a unit test. Here is the full code:
import org.koin.core.KoinApplication
import org.koin.core.component.KoinComponent
import org.koin.core.component.KoinScopeComponent
import org.koin.core.component.createScope
import org.koin.core.component.inject
import org.koin.core.context.startKoin
import org.koin.core.logger.Level
import org.koin.core.scope.Scope
import org.koin.dsl.module
import org.koin.test.KoinTest
import org.koin.test.check.checkModules
import org.koin.test.inject
import kotlin.test.BeforeTest
import kotlin.test.Test
class FixScopingTest : KoinTest {
private val component1: Component1 by inject()
private lateinit var koinApp: KoinApplication
#BeforeTest
fun setup() {
koinApp = startKoin {
modules(
module {
single { Component1() }
scope<Component1> {
scoped { Component2() }
}
}
)
// printLogger(Level.DEBUG)
}
}
#Test
fun verifyKoinApp() {
//component1.component2.print()
koinApp.checkModules()
}
}
class Component1 : KoinComponent, KoinScopeComponent {
override val scope: Scope by lazy { createScope(this) }
val component2: Component2 by inject()
}
class Component2 {
fun print() = println("Component2::print()")
}
exception 1:
com.xycompany.xyproj.xypackage.FixScopingTest > verifyKoinApp FAILED
java.lang.IllegalStateException: Missing MockProvider. Please use MockProvider.register() to register a new mock provider
at org.koin.test.mock.MockProvider.getProvider(MockProvider.kt:10)
at org.koin.test.mock.MockProvider.makeMock(MockProvider.kt:23)
at org.koin.test.check.CheckModulesKt.mockSourceValue(CheckModules.kt:102)
at org.koin.test.check.CheckModulesKt.check(CheckModules.kt:95)
at org.koin.test.check.CheckModulesKt.checkAllDefinitions(CheckModules.kt:86)
at org.koin.test.check.CheckModulesKt.checkModules(CheckModules.kt:72)
at org.koin.test.check.CheckModulesKt.checkModules(CheckModules.kt:40)
at org.koin.test.check.CheckModulesKt.checkModules$default(CheckModules.kt:40)
at com.xycompany.xyproj.xypackage.FixScopingTest.verifyKoinApp(FixScopingTest.kt:43)
Second weird issue appears when you uncomment the commented part so we would have usage of scoped components on DEBBUG level logger:
exception 2:
com.xycompany.xyproj.xypackage.FixScopingTest > verifyKoinApp FAILED
java.lang.NoSuchMethodError: 'double kotlin.time.Duration.toDouble-impl(long, java.util.concurrent.TimeUnit)'
at org.koin.core.time.MeasureKt.measureDurationForResult(Measure.kt:41)
at org.koin.core.scope.Scope.get(Scope.kt:189)
at com.xycompany.xyproj.xypackage.FixScopingTest$special$$inlined$inject$default$1.invoke(KoinTest.kt:53)
at kotlin.SynchronizedLazyImpl.getValue(LazyJVM.kt:74)
at com.xycompany.xyproj.xypackage.FixScopingTest.getComponent1(FixScopingTest.kt:20)
at com.xycompany.xyproj.xypackage.FixScopingTest.verifyKoinApp(FixScopingTest.kt:41)
SETTINGS:
Kotlin Multiplatform Project (test is run in both Andorid and Common packages with the same problem)
VERSIONS:
koin-core: 3.1.3
koin-android: 3.1.3
Looks like you need to add a MockProviderRule when using scoped. It's not required if are not using scopes.
#get:Rule
val mockProvider = MockProviderRule.create { clazz ->
// Mock with your framework here given clazz
// e.g: Mockito.mock(clazz.java)
}
And for it to work you also need to add this dependency to gradle
testImplementation "io.insert-koin:koin-test-junit4:3.1.6"
https://insert-koin.io/docs/reference/koin-test/checkmodules/#allow-mocking-with-a-junit-rule

Kotlin Mockito NullPointerException

There are classes:
#Singleton
class Exchange(
#Client("\${exchange.rest.url}") #Inject val httpClient: RxHttpClient
) : Exchange {
override suspend fun getSymbols(): List<String> {
val response = httpClient.retrieve(GET<String>("/someurl/symbols"), ExchangeInfo::class.java).awaitFirst()
return response.data
.map { it.symbol }.toList()
}
}
#Introspected
#JsonIgnoreProperties(ignoreUnknown = true)
class ExchangeInfo(
val data: List<Symbol>
)
#Introspected
#JsonIgnoreProperties(ignoreUnknown = true)
data class Symbol(
val symbol: String
)
And I want to test the function getSymbols()
I am writing a test class:
import new.project.ExchangeInfo
import new.project.SpotSymbol
import io.micronaut.http.HttpRequest
import io.micronaut.http.client.RxHttpClient
import io.reactivex.Emitter
import io.reactivex.Flowable
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.reactive.awaitFirst
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.withContext
import okhttp3.internal.immutableListOf
import org.junit.jupiter.api.Test
import org.mockito.Mockito.mock
import org.mockito.kotlin.whenever
class ExchangeTest {
#Test
fun getSymbolsTest() = runBlocking {
//the answer I want to receive
val response: Flowable<ExchangeInfo> = Flowable.generate<ExchangeInfo, String>(
java.util.concurrent.Callable<String> { -> "symbol" },
io.reactivex.functions.BiConsumer<String, Emitter<ExchangeInfo>> { t1, t2 -> }
)
val httpClient = mock(RxHttpClient::class.java)
whenever(httpClient.retrieve(HttpRequest.GET<String>("/someurl/symbols"), ExchangeInfo::class.java))
.thenReturn(response)
val exchange = Exchange(httpClient)
//calling the tested method
val result = exchange.getSymbols()
assert(immutableListOf("symbol") == result)
}
}
When running the test, I get:
java.lang.NullPointerException: httpClient.retrieve (GET <… ExchangeInfo :: class.java) must not be null
Can you please tell me how to properly mock httpClient?
it is necessary to do so: doReturn(Flowable.just(ExchangeInfo)).when(httpClient).retrieve(any<HttpRequest<String>>(), any<Class<Any>>())

Add a unit test for Flink SQL

I am using Flink v1.7.1. When I finished a Flink streaming job with tableSource, SQL and tableSink, I have no idea how to add a unit test for it.
I found a good example about how to testing flink sql with the help of user mailing list, here is a example.
package org.apache.flink.table.runtime.stream.sql;
import org.apache.flink.api.common.typeinfo.BasicTypeInfo;
import org.apache.flink.api.common.typeinfo.TypeInformation;
import org.apache.flink.api.java.tuple.Tuple3;
import org.apache.flink.api.java.tuple.Tuple5;
import org.apache.flink.api.java.typeutils.RowTypeInfo;
import org.apache.flink.streaming.api.datastream.DataStream;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
import org.apache.flink.table.api.Table;
import org.apache.flink.table.api.TableEnvironment;
import org.apache.flink.table.api.java.StreamTableEnvironment;
import org.apache.flink.table.runtime.utils.JavaStreamTestData;
import org.apache.flink.table.runtime.utils.StreamITCase;
import org.apache.flink.test.util.AbstractTestBase;
import org.apache.flink.types.Row;
import org.junit.Test;
import java.util.ArrayList;
import java.util.List;
/**
* Integration tests for streaming SQL.
*/
public class JavaSqlITCase extends AbstractTestBase {
#Test
public void testRowRegisterRowWithNames() throws Exception {
StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
StreamTableEnvironment tableEnv = TableEnvironment.getTableEnvironment(env);
StreamITCase.clear();
List<Row> data = new ArrayList<>();
data.add(Row.of(1, 1L, "Hi"));
data.add(Row.of(2, 2L, "Hello"));
data.add(Row.of(3, 2L, "Hello world"));
TypeInformation<?>[] types = {
BasicTypeInfo.INT_TYPE_INFO,
BasicTypeInfo.LONG_TYPE_INFO,
BasicTypeInfo.STRING_TYPE_INFO};
String[] names = {"a", "b", "c"};
RowTypeInfo typeInfo = new RowTypeInfo(types, names);
DataStream<Row> ds = env.fromCollection(data).returns(typeInfo);
Table in = tableEnv.fromDataStream(ds, "a,b,c");
tableEnv.registerTable("MyTableRow", in);
String sqlQuery = "SELECT a,c FROM MyTableRow";
Table result = tableEnv.sqlQuery(sqlQuery);
DataStream<Row> resultSet = tableEnv.toAppendStream(result, Row.class);
resultSet.addSink(new StreamITCase.StringSink<Row>());
env.execute();
List<String> expected = new ArrayList<>();
expected.add("1,Hi");
expected.add("2,Hello");
expected.add("3,Hello world");
StreamITCase.compareWithList(expected);
}
}
the related code is here

Mocking a http response in kotlin

Currently I am working on a hobby project with that I want to learn a bit about kotlin.
I implemented an object that makes HTTP get requests and returns the Json object from the response.
What I'm struggeling with is the mocking of the response or the http framework in my tests.
I think if the framework would provide a class, I could manage the mocking. But as it only provides functions like khttp.get(), I'm a bit confused how to mock that.
Can someone help me, please? :)
Thanks!
The HTTPClient Class:
package dao.http.HTTPClient
import khttp.get
import org.json.JSONObject
import java.net.URLDecoder
class HTTPClient {
fun getClient(): HTTPClient {
return this
}
fun httpRequestGET(url: String): JSONObject {
val r = get(url)
return r.jsonObject
}
}
And the related test Class
import dao.http.HTTPClient
import io.mockk.every
import io.mockk.spyk
import org.hamcrest.MatcherAssert.assertThat
import org.json.JSONObject
import org.junit.jupiter.api.Test
import org.hamcrest.CoreMatchers.`is` as Is
import khttp.responses.GenericResponse
class HTTPClientTest {
#Test
fun testHTTPRequestGET() {
val http_get = spyk(khttp.get( "https://somepage.com/wp-json/tsapi/v1/user/ts/isregistered/12323"))
val httpClient = HTTPClient()
var expectedAnswer: JSONObject = JSONObject("""{"uid":"1","user":"user","is_registered":"true"}""")
every { http_get } returns GenericResponse()
var url = "https://somepage.com/wp-json/tsapi/v1/user/ts/isregistered/12323"
var actualAnswer = httpClient.httpRequestGET(url)
assertThat(actualAnswer.get("user"), Is(expectedAnswer.get("user")))
}
}
you can use it like this:
#Test
fun test() {
mockkStatic("khttp.KHttp")
verify { khttp.get(any()) }
verify(exactly = 1) { khttp.get(url = "http://google.com") }
}