私たちのシステムは、計算やその他のロジックの多くの重要な情報をルックアップタイプテーブルから取得できるように構成されています。例としては、すべての種類の異なるレート(金利や拠出率など)、日付(有効日など)、およびすべての種類のさまざまなその他の情報があります。
なぜ彼らはすべてをこのように構成することに決めたのですか?この情報の一部はかなり頻繁に変更されるためです。たとえば、料金の一部は毎年変動します。彼らは、コードの変更を最小限に抑えることを試みました。期待は、ルックアップテーブルが変更され、コードが機能することだけです(コードの変更はありません)。
残念ながら、それは単体テストを困難にするだろうと思います。一部のロジックでは、100以上の異なるルックアップが行われる場合があります。私は間違いなく私たちのレートを返すモック可能なオブジェクトを作ることができますが、かなりのセットアップになるでしょう。私はそれか、統合テストを使用する(そしてそのデータベースにアクセスする)必要があると思います。私は正しいですか、それとももっと良い方法がありますか?助言がありますか?
編集:
応答が遅れて申し訳ありませんが、私は同じことで他の多くのものをジャグリングしながら、すべてを浸そうとしました。また、実装を同時に実行したいと思いました。私はさまざまなパターンを試して、満足できる解決策を構築しました。満足できないビジターパターンを試してみました。結局、私はオニオンアーキテクチャを使用することになりました。結果に満足しましたか?ちょっと。それが何かだと思います。ルックアップテーブルを使用すると、はるかに困難になります。
以下は、毎年変化するレートのテスト用のセットアップコードの小さな例です(imはfakeiteasyを使用しています)。
private void CreateStubsForCrsOS39Int()
{
CreateMacIntStub(0, 1.00000m);
CreateMacIntStub(1, 1.03000m);
CreateMacIntStub(2, 1.06090m);
CreateMacIntStub(3, 1.09273m);
CreateMacIntStub(4, 1.12551m);
CreateMacIntStub(5, 1.15928m);
CreateMacIntStub(6, 1.19406m);
CreateMacIntStub(7, 1.22988m);
CreateMacIntStub(8, 1.26678m);
CreateMacIntStub(9, 1.30478m);
CreateMacIntStub(10, 1.34392m);
CreateMacIntStub(11, 1.38424m);
CreateMacIntStub(12, 1.42577m);
CreateMacIntStub(13, 1.46854m);
CreateMacIntStub(14, 1.51260m);
CreateMacIntStub(15, 1.55798m);
CreateMacIntStub(16, 1.60472m);
CreateMacIntStub(17, 1.65286m);
CreateMacIntStub(18, 1.70245m);
CreateMacIntStub(19, 1.75352m);
CreateMacIntStub(20, 1.80613m);
CreateMacIntStub(21, 1.86031m);
CreateMacIntStub(22, 1.91612m);
CreateMacIntStub(23, 1.97360m);
CreateMacIntStub(24, 2.03281m);
CreateMacIntStub(25, 2.09379m);
CreateMacIntStub(26, 2.15660m);
CreateMacIntStub(27, 2.24286m);
CreateMacIntStub(28, 2.28794m);
CreateMacIntStub(29, 2.35658m);
CreateMacIntStub(30, 2.42728m);
CreateMacIntStub(31, 2.50010m);
CreateMacIntStub(32, 2.57510m);
CreateMacIntStub(33, 2.67810m);
CreateMacIntStub(34, 2.78522m);
CreateMacIntStub(35, 2.89663m);
CreateMacIntStub(36, 3.01250m);
CreateMacIntStub(37, 3.13300m);
CreateMacIntStub(38, 3.25832m);
CreateMacIntStub(39, 3.42124m);
CreateMacIntStub(40, 3.59230m);
CreateMacIntStub(41, 3.77192m);
CreateMacIntStub(42, 3.96052m);
CreateMacIntStub(43, 4.19815m);
CreateMacIntStub(44, 4.45004m);
CreateMacIntStub(45, 4.71704m);
CreateMacIntStub(46, 5.00006m);
CreateMacIntStub(47, 5.30006m);
CreateMacIntStub(48, 5.61806m);
CreateMacIntStub(49, 5.95514m);
CreateMacIntStub(50, 6.31245m);
CreateMacIntStub(51, 6.69120m);
CreateMacIntStub(52, 7.09267m);
CreateMacIntStub(53, 7.51823m);
CreateMacIntStub(54, 7.96932m);
CreateMacIntStub(55, 8.44748m);
CreateMacIntStub(56, 8.95433m);
CreateMacIntStub(57, 9.49159m);
CreateMacIntStub(58, 10.06109m);
CreateMacIntStub(59, 10.66476m);
CreateMacIntStub(60, 11.30465m);
CreateMacIntStub(61, 11.98293m);
CreateMacIntStub(62, 12.70191m);
CreateMacIntStub(63, 13.46402m);
CreateMacIntStub(64, 14.27186m);
CreateMacIntStub(65, 15.12817m);
CreateMacIntStub(66, 16.03586m);
CreateMacIntStub(67, 16.99801m);
CreateMacIntStub(68, 18.01789m);
CreateMacIntStub(69, 19.09896m);
CreateMacIntStub(70, 20.24490m);
CreateMacIntStub(71, 21.45959m);
CreateMacIntStub(72, 22.74717m);
CreateMacIntStub(73, 24.11200m);
CreateMacIntStub(74, 25.55872m);
CreateMacIntStub(75, 27.09224m);
CreateMacIntStub(76, 28.71778m);
}
private void CreateMacIntStub(byte numberOfYears, decimal returnValue)
{
A.CallTo(() => _macRateRepository.GetMacArIntFactor(numberOfYears)).Returns(returnValue);
}
これは、いつでも変更できるレートの設定コードです(新しい金利が導入されるまでには数年かかる場合があります)。
private void CreateStubForGenMbrRateTable()
{
_rate = A.Fake<IRate>();
A.CallTo(() => _rate.GetRateFigure(17, A<System.DateTime>.That.Matches(x => x < new System.DateTime(1971, 7, 1)))).Returns(1.030000000m);
A.CallTo(() => _rate.GetRateFigure(17,
A<System.DateTime>.That.Matches(x => x < new System.DateTime(1977, 7, 1) && x >= new System.DateTime(1971,7,1)))).Returns(1.040000000m);
A.CallTo(() => _rate.GetRateFigure(17,
A<System.DateTime>.That.Matches(x => x < new System.DateTime(1981, 7, 1) && x >= new System.DateTime(1971, 7, 1)))).Returns(1.050000000m);
A.CallTo(
() => _rate.GetRateFigure(17, A<System.DateTime>.That.IsGreaterThan(new System.DateTime(1981, 6, 30).AddHours(23)))).Returns(1.060000000m);
}
これが私のドメインオブジェクトの1つのコンストラクタです。
public abstract class OsEarnDetail: IOsCalcableDetail
{
private readonly OsEarnDetailPoco _data;
private readonly IOsMacRateRepository _macRates;
private readonly IRate _rate;
private const int RdRate = (int) TRSEnums.RateTypeConstants.ertRD;
public OsEarnDetail(IOsMacRateRepository macRates,IRate rate, OsEarnDetailPoco data)
{
_macRates = macRates;
_rate = rate;
_data = data;
}
なぜ私はそれを好きではないのですか?既存のテストは機能しますが、将来新しいテストを追加する場合は、このセットアップコードを確認して、新しいレートが追加されていることを確認する必要があります。関数名の一部としてテーブル名を使用することで、それをできるだけ明確にしようとしましたが、それはそれが何であるかと思います:)