How to fail dependent tests if one test is failed in XCUITest? - xcuitest

I want to force fail my test if one of my dependent test fails in XCUITest
Ex: func testA() {
}
func testB()
if my func testA() fails then func testB() should also fail

XCUITest does not support dependencies between test cases. We can use the below workaround to overcome that.
class TestClass: XCTestCase {
static var isTestAPassed = true
override func setUp() {
}
override func tearDown() {
if testRun?.test.name == "testA" {
TestClass.isTestAPassed = testRun?.hasSucceeded
}
}
func testA() {
}
func testB() {
XCTAssertTrue(TestClass.isTestAPassed)
}
}

Related

Exception Handling in Kotlin Coroutines Channel fan out

How do I re throw the exception returned from remote call to caller method of handle function ?
suspend fun handle(phMessages: List<PrincipalHierarchyMessage>) {
val messageChannel = Channel<PrincipalHierarchyMessage>()
launchSender(phMessages, messageChannel).invokeOnCompletion {
messageChannel.close()
}
repeat(concurrency) { launchReceiver(messageChannel) }
}
private fun launchSender(phMessages: List<PrincipalHierarchyMessage>, channel: SendChannel<PrincipalHierarchyMessage>) = launch {
phMessages.forEach {
channel.send(it)
}
}
private fun launchReceiver(channel: ReceiveChannel<PrincipalHierarchyMessage>) = launch {
for (msg in channel) {
if (msg.isAddUserToGroup()) {
permsWriterClient.addUserToGroup(msg.groupId, msg.userId, msg.traceId, msg.isLowPriority)
} else if (msg.isRemoveUserFromGroup()) {
permsWriterClient.removeUserFromGroup(msg.groupId, msg.userId, msg.traceId, msg.isLowPriority)
} else {
// log
}
}
}
I have tried calling handle method from a coroutineScope inside try catch, where I expected to catch the exception, but it did not work

Kotlin coroutine exception handling - how to abstract the try-catch

I'm trying to understand exception handling in Kotlin coroutines, so I came up with this very simple scenario where a network call throws an exception and my app has to catch it and handle it.
If I surround my async.await() call with a try-catch block, it works as intended. However, if I try to abstract that try-catch into an extension function, my app crashes.
What am I missing here?
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import kotlinx.coroutines.*
class Main2Activity : AppCompatActivity() {
private val job: Job = Job()
private val scope = CoroutineScope(Dispatchers.Default + job)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main2)
runCode()
}
private suspend fun asyncCallThrowsException(): Deferred<Boolean> =
withContext(Dispatchers.IO) {
Thread.sleep(3000)// simulates a blocking request/response (not on the Main thread, though)
throw(Exception())
}
suspend fun <T> Deferred<T>.awaitAndCatch() {
try {
this.await()
} catch (e: Exception) {
println("exception caught inside awaitAndCatch")
}
}
private fun runCode() {
scope.launch {
//This block catches the exception.
try {
val resultDeferred = asyncCallThrowsException()
resultDeferred.await()
} catch (e: Exception) {
println("exception caught inside try-catch")
}
//This line does not, and crashes my app.
asyncCallThrowsException().awaitAndCatch()
}
}
}
Edit: I had actually forgotten to wrap the call inside an async block. Now, not even the explicit try-catch block works...
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import kotlinx.coroutines.*
class Main4Activity : AppCompatActivity() {
private val job: Job = Job()
private val scope = CoroutineScope(Dispatchers.Default + job)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
runCode()
}
private suspend fun callThrowsException(): String =
withContext(Dispatchers.IO) {
Thread.sleep(3000)// simulates a blocking request/response (not on the Main thread, though)
throw(Exception())
"my result"
}
suspend fun <T> Deferred<T>.awaitAndCatch(): T? {
try {
return this.await()
} catch (e: Exception) {
println("exception caught inside awaitAndCatch")
}
return null
}
private fun runCode() {
scope.launch {
val resultDeferred: Deferred<String> = async { callThrowsException() }
var result: String?
// This doesn't catch the throwable, and my app crashes - but the message gets printed to the console.
try {
result = resultDeferred.await()
} catch (e: Exception) {
println("exception caught inside try-catch")
}
// This doesn't catch the throwable, and my app crashes - but the message gets printed to the console.
result = resultDeferred.awaitAndCatch()
}
}
}
The problem doesn't have to do with how you're catching the exception. The problem is that when your async job fails (throws the exception), it cancels the job you made for your activity.
Even though your code can catch the exception and print the message, the parent job will be terminated ASAP.
Instead of making it like this: val: Job = Job(), try val: Job = SupervisorJob()
A supervisor job isn't cancelled when its children fail, so this won't crash your app.
Or, if you want a way to start an async job that doesn't have this problem, see: Safe async in a given scope
To get to a correct solution, the problem to solve is making it compatible with the principles of structured concurrency.
What exactly is your motivation to use async? What do you plan to do in the meantime, between launching the async and awaiting on it?
If both the async launch and the await call are a part of a single unit of work, and the success of the async call is a prerequisite to the overall success, then wrap the entire unit of work in coroutineScope.
If you want to launch this task in the background and await on it from an Android callback that is invoked later on, then this can't be encapsulated into a single unit of work. You should attach the async task to the top-level CoroutineScope, which should have a SupervisorJob in it.
The proper way to do this is shown in the documentation of CoroutineScope:
class MyActivity : AppCompatActivity(), CoroutineScope by MainScope() {
override fun onDestroy() {
cancel() // cancel is extension on CoroutineScope
}
...
}
Kotlin standard library added the MainScope() delegate as a convenience so you don't get this wrong.

Why am I getting "connection refused" error after restart Spark server?

I have this test classes:
class PostIT {
companion object {
#BeforeClass
#JvmStatic
fun initialise() {
baseURI = "http://localhost:4567"
Server.start()
}
#AfterClass
#JvmStatic
fun tearDown() {
Server.stop()
}
}
//some test cases
}
class UserIT {
companion object {
#BeforeClass
#JvmStatic
fun initialise() {
baseURI = "http://localhost:4567"
Server.start()
}
#AfterClass
#JvmStatic
fun tearDown() {
Server.stop()
}
}
//some test cases
}
and Server object:
object Server {
fun start() {
Spark.init()
prepareRoutes()
}
fun stop() {
Spark.stop()
}
private fun prepareRoutes() {
get("/users", whatever)
//more routes
}
}
When I run both test classes separately, it works fine. But, when I tell IDE to run both test classes, I'm getting connection refused error when second test class is run.
It seems like when server is stopped, it never starts again. It's like Spark.init() is not working after server being stopped.
I've also tried calling Spark.awaitInitialization() after Spark.init().
What am I missing?
Solved! Actually, problem wasn't the server initialization after stopped. We must wait until server is stopped. I found the solution here.
fun stop() {
try {
Spark.stop()
while (true) {
try {
Spark.port()
Thread.sleep(500)
} catch (ignored: IllegalStateException) {
break
}
}
} catch (ex: Exception) {
}
}

Test with JUnit an request

I wanna to test an request with JUnit with an request like this but RxUtils.applySchedulersAndErrorMapper() return null. Is any possibilities to test that?
override fun onContinueClicked(phoneNumber: String) {
mView.showLoading()
mUserService.checkUserApprovedStatus(phoneNumber)
.compose(RxUtils.applySchedulersAndErrorMapper())
.subscribe({ response ->
//Success
}, { error ->
//Error
})
}
here is where I setup the presenter and mUserService for presenter
#Mock
private PhoneContract.View view;
#Mock
private UserService userService;
#Before
public void setup() {
presenter = new PhonePresenter(this.view);
presenter.mUserService = userService;
}
here is the test method
#Test
public void onContinueClicked_SendJustNumbers() {
String phoneNumber = "(01234567890)";
// when
presenter.onContinueClicked(phoneNumber);
// then
verify(view, times(1)).showLoading();
}
and here is the RXUtils class:
class RxUtils {
companion object {
#SuppressLint("CheckResult")
fun <E> applySchedulersAndErrorMapper(): ObservableTransformer<E, E> {
return ObservableTransformer { o ->
o.flatMap(Function<E, ObservableSource<E>> { element ->
val genericResponse = element as GenericResponse<*>
#Suppress("UNCHECKED_CAST")
return#Function Observable.just(genericResponse as E)
}).onErrorResumeNext(Function<Throwable, ObservableSource<E>> { t ->
if (t is ApiException) {
return#Function Observable.error(t)
}
var genericResponse: GenericResponse<*>? = null
return#Function Observable.error(ApiException(t.message ?: "", genericResponse?.result ?: Result()))
})
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io())
}
}
}
}
Here is the stacktrace where I receive null for RxUtils.applySchedulersAndErrorMapper()
java.lang.NullPointerException
If it relates to the SDK, it probably won't work in a unit test. You didn't include your imports, so it's impossible to tell at a glance, but I know from experience that you can't use this in a unit test
AndroidSchedulers.mainThread()
You need to replace that with, say, Schedulers.trampoline()
Example of how to set a custom scheduler for testing
Note, this is only an example, and there are other valid solutions.
class RxUtils {
companion object {
// add this
#VisibleForTesting var mainScheduler = AndroidSchedulers.mainThread()
#VisibleForTesting var ioScheduler = Schedulers.io()
#SuppressLint("CheckResult")
fun <E> applySchedulersAndErrorMapper(): ObservableTransformer<E, E> {
return ObservableTransformer { o ->
o.flatMap(Function<E, ObservableSource<E>> { element ->
val genericResponse = element as GenericResponse<*>
#Suppress("UNCHECKED_CAST")
return#Function Observable.just(genericResponse as E)
}).onErrorResumeNext(Function<Throwable, ObservableSource<E>> { t ->
if (t is ApiException) {
return#Function Observable.error(t)
}
var genericResponse: GenericResponse<*>? = null
return#Function Observable.error(ApiException(t.message ?: "", genericResponse?.result ?: Result()))
})
.observeOn(mainScheduler)
.subscribeOn(ioScheduler)
}
}
}
}
And in your test:
#Before fun setup() {
RxUtils.mainScheduler = Schedulers.trampoline()
RxUtils.ioScheduler = Schedulers.trampoline()
}
#After fun teardown() {
RxUtils.mainScheduler = AndroidSchedulers.mainThread()
RxUtils.ioScheduler = Schedulers.io()
}
EDIT in response to updated post with more information on test
First of all, you should post WAY MORE CODE. It's frustrating having to pull it out of you by dribs and drabs. Anyway. You have the following:
#Mock
private UserService userService;
That creates a mock UserService, sure, but it doesn't stub anything. When you call userService.anyFunctionAtAll(), it will return null by default. There's your NPE. You have to stub it. For example:
Mockito.when(userService.anyFunctionAtAll()).thenReturn(somePredeterminedValue)
Please refer to the Mockito website for more information.

rxjava reactor, Utility to propagate exception

I'm trying to write an utility which automatically propagate checked exception in a reactiv way without writing boiler plate code with static block inside my operators:
public class ReactRethrow {
public static <T, R> Function<T, R> rethrow(Function<T, R> catchedFunc) {
return t -> {
try {
return catchedFunc.apply(t);
} catch (Exception e) {
throw Exceptions.propagate(e);
}
};
}
}
but it stil complaining about IOException here:
Flux.fromArray(resources).map(ReactRethrow.rethrow(resource -> Paths.get(resource.getURI())))
any idea?
Well for a reason I do not clearly understand You have to take as parameter a function which throw exceptions and so declare a specific functionalInterface:
public class ReactRethrow {
public static <T, R> Function<T, R> rethrow(FunctionWithCheckeException<T, R> catchedFunc) {
return t -> {
try {
return catchedFunc.call(t);
} catch (Exception e) {
throw Exceptions.propagate(e);
}
};
}
#FunctionalInterface
public interface FunctionWithCheckeException<T, R> {
R call(T t) throws Exception;
}
}
from here https://leoniedermeier.github.io/docs/java/java8/streams_with_checked_exceptions.html