以下のクラスをテストしたいとする。
PaydayTransaction.h
@interface PaydayTransaction : Transaction
- (id)initWithDb:(PayrollDatabase*)db withLog:(TransactionLog*)log;
- (void)run;
@end
普通にテストを書くとこうなる。
PaydayTransactionTests.h
@interface PaydayTransactionTests : SenTestCase
{
PayrollDatabase* _db;
TransactionLog* _log;
}
@end
PaydayTransactionTests.m
@implementation ExtractInterfaceTests
- (void)setUp
{
[super setUp];
// Set-up code here.
_db = [[PayrollDatabase alloc] init];
_log = [[TransactionLog alloc] init];
}
- (void)testPayday
{
PaydayTransaction* t = [[PaydayTransaction alloc] initWithDb:_db withLog:_log];
[t run];
STAssertEquals(90, _db.stock, @"_db.stock should be 90");
}
@end
このテストはPaydayTransactionクラスを調べるためのものだが、テストの中でPayrollDatabaseクラスとTransactionLogクラスに依存している。PaydayTransactionクラスの挙動に焦点を絞るために、TransactionLogクラスへの依存を排除したテストを書きたいとする。
つまり、以下のようなテストを書きたい。
PaydayTransactionTests.h
@interface ExtractInterfaceTests : SenTestCase
{
PayrollDatabase* _db;
}
@end
PaydayTransactionTests.m
@implementation ExtractInterfaceTests
- (void)setUp
{
[super setUp];
// Set-up code here.
_db = [[PayrollDatabase alloc] init];
}
- (void)testPayday
{
FakeTransactionLog* aLog = [[FakeTransactionLog alloc] init];
PaydayTransaction* t = [[PaydayTransaction alloc] initWithDb:_db withLog:aLog];
[t run];
STAssertEquals(90, _db.stock, @"_db.stock should be 90");
}
@end
Objective-Cはコンパイラが型チェックを行わないので、このままでもコンパイルは通るが、メソッドのシグナチャを合わせることにする。
まずTransactionLogクラスのメソッドを確認する。
TransactionLog.h
@interface TransactionLog : NSObject
- (void)saveTransaction:(TransactionLog*)transaction;
- (void)recordErrorWithCode:(int)code;
@end
次に、以下のようなTransactionRecorderプロトコルおよびクラスをつくる。
TransactionRecorder.h
@protocol TransactionRecorder <NSObject>
- (void)saveTransaction:(TransactionRecorder*)transaction;
- (void)recordErrorWithCode:(int)code;
@end
@interface TransactionRecorder : NSObject <TransactionRecorder>
@end
TransactionRecorder.m
@implementation TransactionRecorder
- (void)saveTransaction:(TransactionRecorder*)transaction
{
}
- (void)recordErrorWithCode:(int)code;
{
}
@end
そして、TransactionLogクラスとFakeTransactionLogクラスにはTransactionRecorderプロトコルを実装する。
TransactionLog.h
@interface TransactionLog : NSObject <TransactionRecorder>
@end
FakeTransactionLog.h
@interface FakeTransactionLog : NSObject <TransactionRecorder>
@end
そして、PaydayTransactionクラスからはTransactionRecorderクラスを参照するようにする。
PaydayTransaction.h
@interface PaydayTransaction : Transaction
- (id)initWithDb:(PayrollDatabase*)db withLog:(TransactionRecorder*)log;
- (void)run;
@end
これでいいのかな?ちょっと不安。
ブログやってます:PAPA-tronix !