Nimble: Best approach for notification testing with string name

Created on 14 Apr 2016  路  4Comments  路  Source: Quick/Nimble

Usually I'm sending notifications using postNotificationName:, however Nimble example test cases use NSNotification object and equal matcher:

 func testPassesWhenExpectedNotificationIsPosted() {
        let testNotification = NSNotification(name: "Foo", object: nil)
        expect {
            self.notificationCenter.postNotification(testNotification)
        }.to(postNotifications(equal([testNotification]), fromNotificationCenter: notificationCenter))
    }

what is the most concise way of testing notification name identity without using notification objects?

Most helpful comment

@raphaeloliveira

public func equalNames(_ expectedNames: [Notification.Name]) -> Predicate<[Notification]> {
    return Predicate.define("equal <\(stringify(expectedNames))>") { actualExpression, msg in
        guard let actualValue = try actualExpression.evaluate() else {
            return PredicateResult(status: .fail, message: msg)
        }

        let actualNames = actualValue.compactMap { $0.name }
        let matches = expectedNames == actualNames
        return PredicateResult(bool: matches, message: msg)
    }
}

All 4 comments

If you are feeling the need to slim down tests like this, I'd suggest throwing in a custom matcher that lets you be more specific with the assertion. Something like this:

func equalNames(expectedNames: [String]) -> NonNilMatcherFunc<[NSNotification]> {
    return NonNilMatcherFunc { actualExpression, failureMessage in
        failureMessage.postfixMessage = "equal names <\(stringify(expectedNames))>"
        guard let actualValue = try actualExpression.evaluate() else { return false }
        return actualValue.map({ $0.name }) == expectedNames
    }
}

which would let you write the test this way:

func testPassesWhenExpectedNotificationIsPosted() {
    expect {
        self.notificationCenter.postNotification(NSNotification(name: "Foo", object: nil))
    }.to(postNotifications(equalNames(["Foo"]), fromNotificationCenter: notificationCenter))
}

Hope this helps!

@briancroom thanks for the snippet, I'm going to stick with this approach

Hi @briancroom, I'm struggling to translate your matcher to latest Nimble version. By any chance would you be able to help on this please?

@raphaeloliveira

public func equalNames(_ expectedNames: [Notification.Name]) -> Predicate<[Notification]> {
    return Predicate.define("equal <\(stringify(expectedNames))>") { actualExpression, msg in
        guard let actualValue = try actualExpression.evaluate() else {
            return PredicateResult(status: .fail, message: msg)
        }

        let actualNames = actualValue.compactMap { $0.name }
        let matches = expectedNames == actualNames
        return PredicateResult(bool: matches, message: msg)
    }
}
Was this page helpful?
0 / 5 - 0 ratings

Related issues

Blackjacx picture Blackjacx  路  9Comments

aaroncrespo picture aaroncrespo  路  10Comments

zachlucas picture zachlucas  路  5Comments

gapl picture gapl  路  5Comments

ScottRobbins picture ScottRobbins  路  7Comments