clifgray clifgray - 24 days ago 6
CoffeeScript Question

Test for Apple Push Notification

I am using node.js (server framework) and mongoose.js (mongo based schema modeling) as the backend for an iOS app and I am using Mocha (test framwork) to make sure everything works.

What I really want to know, and can find no documentation on, is how to test on the server if the push notifications are being appropriately sent. I am using apnagent and at the moment I can see that push notifications are being sent correctly by manually checking my device but I am having difficulty finding an automated way to test that they are working correctly.




That may be enough of a description to answer at a high level what needs to be done. But in case it is not here is the actual code:

Mongoose Model fires off a push notification upon creation:

#this code is called after this model is saved in mongodb
eventModel.post 'save', (doc) ->
#push the message
sendMessageToDevice = (event, token) ->
message =
event_body:
eventId: event._id
lat: event.lngLat[1]
lng: event.lngLat[0]
agent.createMessage()
.device(token)
.alert('New Event! ' + event.description)
.set(message)
.send()

#cycle through the users to push to
#get all the unique device tokens in the database for APN
users.getAllUniqueDeviceTokens (error, devices) ->
if error then return util.handleError error
console.log "Sending push notices to all devices (%d):", devices.length
console.log devices
for token in devices
sendMessageToDevice doc, token

#send some verification here that the code ran correctly???


Then in my Mocha test file I have:

it 'should receive push notification from fort creation', (done) ->
#some logic here to verify that push notifications were sent
done()

Answer

In many situations, while writing tests, it is either impossible or simply too dangerous to verify that an action has really taken place (i.e. a push notification has been delivered). Imagine writing a unit test for the rm command where you would like to ensure that doing rm -rf / succeeds. Obviously, you cannot let this action take place and verify that your root partition is indeed empty!

What you can do, however (and should do, really), is verify that whatever commands, routines or other actions necessary to accomplish the task are being invoked correctly, without actually allowing them to take place.

In your particular situation, you do not need to verify that your push notification has been delivered because your application is not responsible for the notification's delivery. However, you can test that the push notification is being correctly delivered to the push server.

So, instead of testing for successful delivery, you test

  1. Whether the outgoing request is properly formatted (i.e. JSON is valid)
  2. Whether it contains the data you expect it to contain (i.e. a field in JSON is present and contains expected data)
  3. Whether the authentication token required by the server is included
  4. Whether the target server is correct (i.e. you are indeed sending the data to xxx.apple.com and not to localhost)

Ideally, these test requests will not even reach the target server - doing so would mean you are relying on two factors that are not always perfectly stable:

  • network connectivity
  • target server availability and proper functionality

In the past, I dealt with this so that I first manually issued a correct request, captured the response and then mocked the whole communication in the unit test (using i.e. nock. That way, I am completely in control of the whole communication.