私は C# でサーバー コンポーネントを作成しており、単体テストには Pex を使用しています。
特定のメソッドの複雑なパラメーター化された単体テストがあります。ここで、特定の assert ブロックを追加するとすぐに、一部の pex 探索の実行が失敗し、メソッドの終了行 (括弧の右側) で NullReferenceException が発生することがわかりました。失敗した実行をデバッグすると、まったく問題なく実行されます。
私は間違いを犯しましたか、これは pex のバグですか?
ありがとう!
[PexMethod]
public Task Start(CancellationToken cancellationToken,
int workingEndpoints, // endpoints that run succesfully
int failingEndpoints, // endpoints that fail immidiatly
int brokenEndpoints) // endpoints that return null for their task
{
PexAssume.IsTrue(workingEndpoints >= 0);
PexAssume.IsTrue(failingEndpoints >= 0);
PexAssume.IsTrue(brokenEndpoints >= 0);
PexAssume.IsTrue(workingEndpoints + failingEndpoints + brokenEndpoints >= 1);
// create fake endpoints based on the count
List<IHostEndpoint> fakeEndpoints = new List<IHostEndpoint>();
Exception failedTaskException = new Exception();
// Create a few endpoint stubs for testing purposes and add them to the list (commented away for relevance)
// create and start the host
Host host = new Host(fakeEndpoints.ToArray());
Task result = host.Start(cancellationToken);
PexAssert.IsNotNull(result);
if (failingEndpoints > 0 || brokenEndpoints > 0)
{
PexAssert.IsNotNull(result.Exception);
int failedEndpointExceptionCount = 0;
int brokenEndpointExceptionCount = 0;
result.Exception.Flatten().Handle(innerException =>
{
if (innerException == failedTaskException)
failedEndpointExceptionCount++;
else
brokenEndpointExceptionCount++;
return true;
});
// after one broken endpoint, the run method should stop starting more endpoints
int brokenEndpointExpectedCount = Math.Min(1, brokenEndpoints);
PexAssert.AreEqual(failedEndpointExceptionCount, failingEndpoints);
PexAssert.AreEqual(brokenEndpointExceptionCount, brokenEndpointExpectedCount);
}
return result;
}
編集
1 つの想定としては、非同期コードが原因で、Pex で何らかの問題が発生したことが考えられます。私はすべての実行をチェックし、さらにホストの開始方法を偽造しました。非同期メソッドはありません。場合によっては1つのタスクを作成しますが、同期的に実行します(以下の証明)
Task endpointTask = endpoint.Start(innerCancellationToken);
if (endpointTask == null)
{
// This endpoint is broken, for simplicity we raise an exception in the normal pipe
Task faultedTask = new Task(() =>
{
throw new InvalidOperationException("Endpoint returned a null valued task which is not allowed");
});
faultedTask.RunSynchronously();
innerTasks.Add(faultedTask);
break;
}
else
{
innerTasks.Add(endpointTask);
}
IHostEndpoint スタブは、値/状態が直接設定された TaskCompletionSource を使用して作成されます。