5

We can test thrown errors with XCTAssertThrowsError. Async things can be tested with expectation. I have some method which dispatch work to a background thread and can at some point throw an error.

Is it possible to expect an error be thrown somewhere in the future? I need to combine expectation and XCTAssertThrowsError I think, but I do not know how.

Reproduction project: https://github.com/Jasperav/ThrowingAsyncError. Just clone the project and run the tests, one of them will fail. I made a class which will crash after a few seconds after it has been allocated. I want to make sure it keeps crashing after a few seconds, so I want a test case for it.

J. Doe
  • 11,360
  • 7
  • 50
  • 91
  • If the functions your testing throw. Shouldn't you just be doing a do / catch. –  Amerino Oct 30 '19 at 21:28
  • @Amerino Doesn't work when the methods are async. – J. Doe Oct 30 '19 at 21:38
  • 1
    @J.Doe would it be possible to provide some sample code? That may make it a little bit easier to understand how exactly this background work is used. For instance, is this background work called with a completion handler, etc. – Anthony Dito Nov 06 '19 at 01:51
  • Would you be able to just make your unit test throw as well? Then if the async call throws within the unit test, assuming you're not catching the error it would fail the test. – jlowe Nov 06 '19 at 15:22
  • @AnthonyDito Ok, I made one, see my edit – J. Doe Nov 06 '19 at 21:33
  • I am not sure, but maybe [this post] (https://stackoverflow.com/a/34301948/1987726) solves your problem? – Reinhard Männer Nov 07 '19 at 13:55
  • I deleted my previous answer which didn't answer your question. I did dig into it a bit more, and 1) I'm not sure you can ever catch a fatalError, 2) even if you replace that with a thrown exception, I'm not sure you can catch a throw on an async thread unless you have some way to insert a closure into that thread. (And even then, it's not clear to me exactly how you'd do it.) – ajgryc Nov 08 '19 at 04:26

1 Answers1

0

I took a look at the reproduction project to see what you were trying to accomplish here...

To my understanding:

XCTAssertThrowsError are assertions that takes in a block that can throw. They just happen to assert that an error is thrown in a synchronous block when it's done running.

XCTestExpectation are classes that keep track of whether or not requested conditions are met. They are for keeping track of asynchronous code behavior objects/references need to be kept and checked later.

What you seem to be trying to do is make something like XCTestExpectation work the same way XCTAssertThrowsError does, as in make an synchronous assertion that an asynchronous block will throw. It won't work quite that way because of how the code runs and returns.

The asynchronous code you refer to does not throw (timer initializer). As far as I know, there aren't any asynchronous blocks that can throw. Perhaps the question you should be asking is how can we make a synchronous operation choose to run synchronously sometimes, but also asynchronously when it feels like...

Alternatively for some additional complexity in every class you would like to test I've made a solution with what is almost bare minimum to make this easily testable and portable...

https://github.com/Jasperav/ThrowingAsyncError/pull/1/files

May I ask why you would ever want to do something like this?