I am testing the following method with OCMock:
- (void)methodToTest {
[self.someObject doFirstActionWithParam:#"aparam" completion:(void(^)(BOOL success)) {
if (success) {
[self.someObject doSecondActionWithParam:#"aparam" completion:(void(^)(BOOL success)) {
if (success) { [self doSomething]; }
}];
}
}];
}
I have a partial mock for self.someObject.
The doFirstActionWithParam, I am able to set an expectation for. I am also overriding the completion block (via NSInvocation and invoking a YES completion).
However, I am not able to get the call for doSecondActionWithParam method. I also set up expectation for doSomething method. That never comes through.
Any suggestion for an approach to test nested completion blocks?
There shouldn't be a difference due to the nesting level when you mock a method (stub or expect). As you didn't include your test code it's really difficult to diagnose the problem. My assumption is that the block that is passed to doFirstActionWithParam:completion: is never invoked, in which case doSecondActionWithParam:completion: would als never be invoked.
Related
I want an embedded view to be able to call a function from the parent view, so I'm trying to have the child reference its parent by injection. This seems to work fine as long as the embedded view is created onDock:
class TestView : View() {
override val root = vbox {
label("Parent Label")
}
init {
println("Parent is instantiating.")
}
override fun onDock() {
val child = find(TestView2::class)
root.add(child)
}
fun doThing() {
println("Parent is doing a thing.")
}
}
class TestView2 : View() {
val parentClass: TestView by inject()
override val root = hbox {
label("Sub-view label 1")
label("Sub-view label 2")
}
init {
println("Sub-view is instantiating.")
parentClass.doThing()
}
}
I'd like it to be cleaner though. I'd prefer it if I was able to use the find function while creating the parent root. That's a problem, as calling the child view within any part of the init process creates a circular instantiation loop. Any way to avoid this or will I just have to settle for onDock and deal with it?
EDIT:
Just to note, I tried the onDock method again in a real, more complicated application and I got a cycle detection error. So even that method is not guaranteed to work.
You can create cyclic dependencies, but you can't call functions in both component's init block, as that would be impossible to resolve. The main takeaway here is that you're probably doing something you shouldn't. Views should not communicate with each other directly. This creates a tight coupling and prevents reuse. Instead you should communicate with one of the following:
State from a ViewModel
Controller function calls
Events using the EventBus
Since your code example is made up, it's not known what exactly you're trying to achieve in your actual app, but you will find the correct approach in the list above.
I see the urge to call functions in views and setting data directly into ui components instead of using bindings a lot, and in absolutely every case there is a much better way to solve the problem :)
Since Xcode 10.1(maybe 10) when I create a Unit test file I don't have calls super.tearDown() and super.setUp() .
I've not seen such changes in release notes.
In documentation https://developer.apple.com/documentation/xctest/xctestcase/understanding_setup_and_teardown_for_test_methods are still here.
So my question should I still write super.tearDown() and super.setUp()?
class SomethingTests: XCTestCase {
override func setUp() {
// Put setup code here. This method is called before the invocation of each test method in the class.
}
override func tearDown() {
// Put teardown code here. This method is called after the invocation of each test method in the class.
}
func testExample() {
// This is an example of a functional test case.
// Use XCTAssert and related functions to verify your tests produce the correct results.
}
func testPerformanceExample() {
// This is an example of a performance test case.
self.measure {
// Put the code you want to measure the time of here.
}
}
}
For a direct subclass of XCTestCase, there never was any change of behavior for not calling super.setUp(). That's because setUp and tearDown are template methods with empty implementations at the top level.
Though there's no change in behavior, omitting the calls to super means that if you create a test hierarchy with more than one level, you'll have to add them back.
When would you ever have more than one level? There are two cases:
When you want to reuse the same tests for different scenarios.
When you subclass XCTestCase to make a customized helper.
These don't happen every day. But they do happen. Deciding "I need it here, but I don't need it there" is perilous. So I'd just call super all the time.
I keep running into this issue wherein I'd like to trigger an event (void) during a scheduled update or tick method - but only trigger it once. The problem is that it gets triggered every time update/tick gets called (each frame). Depending on what method is being called, this slows down the game and occasionally crashes (e.g. addChild already added). I've used a BOOL (e.g. eventTriggered) before to try to handle this situation but am wondering if that is the only and/or best way?
If you're using cocos2d 2.0 just use:
[self scheduleOnce:#selector(yourMethod:) delay:3.0f];
In all other cases simply unschedule the scheduled selector:
-(void) yourScheduledMethodThatShouldOnlyRunOnce:(ccTime)delta
{
[self unschedule:_cmd];
// do stuff once
}
If it's a custom method you need to have some condition that fires the method call, for example:
-(void) update:(ccTime)delta
{
if (runThisNowButOnlyOnce)
{
runThisNowButOnlyOnce = NO;
[self runThisNowButOnlyOnceMethod];
}
}
You just need to figure out when and where to set runThisNowButOnlyOnce to YES. Also don't forget to add it as an ivar to the #interface.
I am trying to load objects synchronously with RestKit and to do that I am using [anObjectLoader sendSynchronously] on a background thread. Then in the RKObjectLoader didFinishLoad: the application is currently stopping at the first line: NSAssert([NSThread isMainThread], #"RKObjectLoaderDelegate callbacks must occur on the main thread");
Looking at the documentation, the sendSynchronously method from the RKRequest class says that the request will be synchronously requested and a hydrated response object will be returned.
This is a snapshot of my code:
RKObjectLoader *anObjectLoader = [self.objectManager loaderWithResourcePath:resourcePath];
NSLog(#"Response: %#", [anObjectLoader sendSynchronously]);
On console:
*** Assertion failure in -[RKManagedObjectLoader didFinishLoad:], ...RestKit/Code/ObjectMapping/RKObjectLoader.m:423
Is it Ok to use RestKit with synchronous calls?
Are there better ways to send synchronous requests?
Am I missing something?
You should never make synchronous calls. Use the send method and catch the response using either delegates or block callbacks. Among other things, this method is optimized for network bandwidth usage and also handles threading correctly.
As an aside, the reason RKObjectLoader requires the main thread is because that is where your main object context is.
I recently had this same question. I figured out how to send a synchronous call using blocks and it's actually quite nice. Basically you do whatever restkit call you were intending to do, but instead of setting the delegate to self, you use usingBlock. Then, within that block you can handle the various responses from your API call.
Block Example (APIUser is class I wrote that represents the current user):
[[RKObjectManager sharedManager] loadObjectsAtResourcePath:[#"/api/users/" stringByAppendingString:userName] usingBlock:^(RKObjectLoader* loader) {
loader.onDidLoadResponse = ^(RKResponse *response) {
NSLog(#"Response: \n%#", [response bodyAsString]);
};
loader.onDidLoadObjects = ^(NSArray *objects) {
APIUser *apiUser = [objects objectAtIndex:0];
};
loader.onDidFailWithError = ^(NSError *error) {
NSLog(#"Response: \n%#", [response bodyAsString]);
};
}];
My original question and answer can be found here.
For an iPhone app, I'm using a NSOperationQueue to limit access to the SQLite database to one query at a time. I created a subclass of NSOperation and in the main function I have the following:
- (void)main
{
// ... other code here ...
if( [_delegate respondsToSelector:#selector(queryCompleted:)] )
{
[_delegate performSelectorOnMainThread:#selector(queryCompleted:)
withObject:self
waitUntilDone:NO];
}
}
Delegate side:
- (void)queryCompleted:(QueryOperation*)aQueryOperation
{
// Breakpoint here allows me to explore and see the members of aQueryOperation
id results = [aQueryOperation resultSet]; // Crashes here
// ... more code here ...
}
The reason I am passing self is to allow the delegate to access the ID for the query operation (in the case where there is more than one request open per delegate) and the results from the query.
In the documentation for performSelectorOnMainThread:withObject:waitUntilDone:, it clearly states:
"This method retains the receiver and the arg parameter until after the selector is performed."
However when the delegate method tries to access the argument, an "EXC_BAD_ACCESS" exception is thrown. Any thoughts on why?
Oddly enough, if I set a breakpoint before the crashing reference to the NSOperation object, the debugger permits me to see the object instance and the values of all the parameters.
Try setting the waitUntilDone: parameter to YES. Possibly there is a race condition which is allowing the NSOperation to deallocate itself.