次のコードが与えられた
public class Entity
{
public string Name { get; set; }
public string Status { get; set; }
}
public interface IRepository
{
void InsertEntity(Entity entity);
void UpdateEntity(Entity entity);
}
public class Processor
{
private IRepository _repository;
public Processor(IRepository repository)
{
_repository = repository;
}
public void Execute(string name)
{
var entity = new Entity() { Name = name, Status = "Initialized" };
_repository.InsertEntity(entity);
// do other things with the entity
entity.Status = "Processed";
_repository.UpdateEntity(entity);
}
}
リポジトリがExecuteメソッド内で呼び出されているかどうかを確認する単体テストを記述して、InsertEntityメソッドを使用してエンティティの値を保存できます。つまり、InsertEntityが呼び出されたときに、エンティティのStatusプロパティの値が「Initialized」であることを確認したいと思います。したがって、私の単体テストは次のようになります。
[TestMethod]
public void ShouldSaveEntityWithStatusInitialized()
{
var mock = new Mock<IRepository>();
var processor = new Processor(mock.Object);
processor.Execute("test");
mock.Verify(m => m.InsertEntity(It.Is<Entity>(e => e.Status == "Initialized")), Times.Once()); // fail
}
ただし、このコードは、Status = "Initialized"でInsertEntityメソッドを呼び出しても失敗します(デバッグしました)。これは、Executeメソッドの実行中にエンティティオブジェクトが変更され(最後にStatusプロパティが "Processed"に変更され)、Moqが変更されたオブジェクトに対して呼び出しを検証するためだと思います。実際、この他の単体テストはうまく機能します。
[TestMethod]
public void ShouldUpdateEntityWithStatusProcessedAtTheEnd()
{
var mock = new Mock<IRepository>();
var processor = new Processor(mock.Object);
processor.Execute("test");
mock.Verify(m => m.InsertEntity(It.Is<Entity>(e => e.Status == "Processed")), Times.Once());
}
最初の単体テストを機能させるために私が見つけた唯一の方法は、次の回避策を使用することです。Moqのコールバック機能を使用してStatusプロパティの値を保存し、後でそれをアサートします。
[TestMethod]
public void ShouldSaveEntityWithStatusInitialized_withWorkaround()
{
var mock = new Mock<IRepository>();
var processor = new Processor(mock.Object);
string status = string.Empty;
mock.Setup(m => m.InsertEntity(It.IsAny<Entity>())).Callback((Entity e) => status = e.Status);
processor.Execute("test");
Assert.AreEqual("Initialized", status);
}
しかし、私はそれが好きではありませんでした。すべての実行が完了した後ではなく、STU(テスト対象システム)の実行中にモックオブジェクトに対して行われた呼び出しをMoqに検証させる方法があるかどうかを知りたいです。
ありがとう