What is the best practice for testing NSDateFormatter methods? For example, lets say I have a method:
- (NSString *)formatStringFromDate:(NSDate *)date {
NSDateFormatter *f = [[NSDateFormatter alloc] init];
[f setTimeStyle:NSDateFormatterShortStyle];
[f setDateStyle:NSDateFormatterNoStyle];
return [f stringFromDate:date];
}
There are two ways I can think of testing this method using Kiwi:
1) Create the same formatter in the unit test:
it(@"should format a date", ^{
NSDate *date = [NSDate date];
NSDateFormatter *f = [[NSDateFormatter alloc] init];
[f setTimeStyle:NSDateFormatterShortStyle];
[f setDateStyle:NSDateFormatterNoStyle];
[[[testObject formatStringFromDate:date] should] equal:[f stringFromDate:date]];
});
2) Explicitly write the intended output:
it(@"should format a date", ^{
NSDate *date = [NSDate dateWithTimeIntervalSince1970:1385546122];
NSDateFormatter *f = [[NSDateFormatter alloc] init];
[f setTimeStyle:NSDateFormatterShortStyle];
[f setDateStyle:NSDateFormatterNoStyle];
[[[testObject formatStringFromDate:date] should] equal:@"9:55 am"];
});
Now, to me, #1 seems a bit redundant. I know the test will pass as I'm essentially duplicating the method in my unit test.
Method #2 is a non-starter, as it is incredibly fragile. It completely relies on the test devices current locale being what you'd expect.
So my question is: is there a more appropriate method to test this method, or should I just go ahead with test method #1.
As you say in your comment, what you want to test is that the cell's detailTextLabel's text is set to date with the expected format when a date is present.
This can be tested in several different ways, I expose here the one I would go for.
First of all, creating a date formatter each time we want to format a date is not efficient and it makes it more difficult to test.
So what I suggest is to create a date formatter property in your table view controller:
For the date formatter I would create a simple test that verifies the timeStyle and dateStyle. I am not familiar with Kiwi so I use OCUnit assertions:
After having this, the idea is to create a test that verifies that the cell returned by
tableView:cellForRowAtIndexPath:has its detailTextLabel's text set with the string returned by the formatter. As you said testing the string returned by the date formatter is fragile so we can mock it, stubstringFromDate:returning a constant and verify that the detailTextLabel's text is set to that constant.So we write the test. I'd try to write it with Kiwi mocks, so sorry if I do something wrong - the idea is the important thing:
And the method to satisfy that test would be something like this:
Hope it helps.