次のコードでFindPolicyToBeResent()をテストしたいと思います。利用できるオプションがいくつかありますが、私のアプローチ、つまり最後のオプションで問題がない場合にも、他の誰かがこの状況にどのようにアプローチするか知りたいですか?
- FindPolicyToBeResent()をパブリックにします。これは、テストの唯一の理由で実装を公開し、インターフェイスを混乱させるため、オプションではありません
- パブリックAPIのみを使用した単体テストですが、returnステートメントで直接フィルタリングしているコレクションを公開することはなく、セキュリティ上の理由から公開できないため、これは難しい場合があります。これは、限られたテストしかできないことを意味します
- 通常、この状況ではコードを新しいオブジェクトに分割しますが、この場合は正しくないと感じます。このフィルターがシステム内の他の場所で再利用されることは予測できないため、メソッドを公開するよりも前に公開するよりも良い方法はありません。誰もが単一責任スティック(正当化される)で私を殴ります。コーディングはバランスをとる行為であり、KeepItSimpleの原則を破るような気がします。それは、実際に個別の単一の責任を持っているのではなく、テストを提供するためのクラスを作っているような気がします。さらに、ファイルとクラスが肥大化します。
- コードをIEnumerableの拡張メソッドにしてテスト可能にすることはできますが、このフィルターが他の場所で使用されることは予測できないため、このクラスに残っている方が理にかなっています。
- 最後のオプションと好みですが、ちょっとしたハックと見なされるかもしれませんが、verify()を使用してコードのさらに下にあるdocumentResenderRepository.CanPolicyBeResent(policy.Id)のモックをテストし、ハチがヒットした回数を確認します。これが良い考えかどうかわかりませんか?考え?
私の好みは最後のオプションですが、少し汚い感じがします。下部に例があります
public class DocumentResendService : IDocumentResendService
{
#region Member Variables
...
#endregion
#region Constructors
...
#endregion
#region Accessors
...
#endregion
#region Methods
public IDocumentResendResponse ResendDocuments()
{
if (!IsInputsValid())
{
return response;
}
RecordRequestAttempt();
if (RequestLimitIsReached())
{
return response;
}
FindPolicyToBeResent();
if(PolicyCanNotBeResent())
{
return response;
}
RequestDocumentToBeResent();
return response;
}
private bool IsInputsValid()
{
..
}
private void RecordRequestAttempt()
{
...
}
private bool RequestLimitIsReached()
{
...
}
// I want to test this method which basically just filters the policies
private void FindPolicyToBeResent()
{
var allPolicies = policyDocumentRepository.GetPolicy(AgentCode, Email, PostCode, SearchDate, BirthDate);
policies = allPolicies.Where(currentPolicy => currentPolicy.IsActive() || currentPolicy.IsInTheFuture());
if (policies.Count() == 0 )
{
policies = allPolicies.FilterToPolicyThatHasEndedMostRecently();
}
}
private bool PolicyCanNotBeResent()
{
if (policies == null || !policies.Any())
{
response.Add(ErrorCode.PolicyCanNotBeFound);
return true;
}
foreach (var policy in policies)
{
// I could mock this line and use a verify here which policy id's are passed in
if (documentResenderRepository.CanPolicyBeResent(policy.Id) == false)
{
response.Add(ErrorCode.UnableToResendDocument);
}
}
return response.Errors.Any();
}
private void RequestDocumentToBeResent()
{
...
}
#endregion
}
これが最後のオプションの単体テストソリューションですが
[TestFixture]
public class FindPolicyToBeResentTest : DocumentResenderTestsBase
{
private readonly List<Policy> allPolicies = new List<Policy>();
public FindPolicyToBeResentTest()
{
var day = -250;
for (int i = 1; i < 6; i++)
{
var policy = new Policy
{
Id = i,
StartDate = DateTime.Now.AddDays(day)
};
day = day + 100;
policy.EndDate = DateTime.Now.AddDays(day);
allPolicies.Add(policy);
}
}
private void SetUpDocumentResender(IEnumerable<Policy> policies)
{
SetUpObjectDefaultsForDocumentResenderCreation();
policyRepositoryMock.Setup(y => y.GetPolicy(It.IsAny<string>(),
It.IsAny<string>(),
It.IsAny<string>(),
It.IsAny<DateTime>(),
It.IsAny<DateTime>()))
.Returns(policies);
documentResendService = CreateDocumentResendService();
SetDocumentResenderDefaults();
}
[Test]
public void PoliciesThatAreNotActiveOrAreInThePastShouldBeFilteredOut()
{
SetUpDocumentResender(allPolicies);
documentResendService.ResendDocuments();
foreach (var policy in allPolicies)
{
if (policy.IsActive() || policy.IsInTheFuture())
{
documentResenderRepositoryMock.Verify(x => x.CanPolicyBeResent(policy.Id), Times.AtLeastOnce());
}
else
{
documentResenderRepositoryMock.Verify(x => x.CanPolicyBeResent(policy.Id), Times.Never());
}
}
}
[Test]
public void IfNoPoliciesAreFoundThatAreSuitableForDocumentResendingThenGetThePolicyThatHasMostRecentlyExpired()
{
var unsuitablePolicies = allPolicies.Where(x => x.IsActive() == false && x.IsInTheFuture() == false).OrderBy(x => x.EndDate);
var policyWithClosestToEndDateToNow = unsuitablePolicies.ToList().Last();
SetUpDocumentResender(unsuitablePolicies);
documentResendService.ResendDocuments();
documentResenderRepositoryMock.Verify(x => x.CanPolicyBeResent(policyWithClosestToEndDateToNow.Id), Times.AtLeastOnce());
foreach (var policy in allPolicies.Where(policy => policy != policyWithClosestToEndDateToNow))
{
documentResenderRepositoryMock.Verify(x => x.CanPolicyBeResent(policy.Id), Times.Never());
}
}
}