NuGetで公開されているMoq.EntityFrameworkCoreを使ってテストソースを書いていた時に少し躓いたところがあったので残しておく。
躓いたところ
DbSetに渡された引数の検証を行おうとした時にどうMock Objectを渡せばいいのか分からなかった。
解決策
まずテスト対象のソースはこんな感じ。
public class UsersService
{
private readonly UsersContext usersContext;
public UsersService(UsersContext usersContext)
{
this.usersContext = usersContext;
}
public void AddUser(string name) {
var user = new User()
{
Name = name
};
usersContext.Users.Add(user);
usersContext.SaveChanges();
}
}
引数で受け取った値を元にメソッド内でモデルを生成してそのまま永続化する処理。
次にテストソース
[TestClass]
public class UsersServiceTest
{
[TestMethod]
public void TestSample()
{
// arrange
var dbSetMock = new Mock<DbSet<User>>();
User param = null;
dbSetMock.Setup(x => x.Add(It.IsAny<User>())).Callback<User>(x => param = x);
var userContextMock = new Mock<UsersContext>();
userContextMock.Setup(x => x.User).ReturnsDbSet(new User[0], dbSetMock);
var usersService = new UsersService(userContextMock.Object);
// act
usersService.AddUser("test user1");
// assert
Assert.AreEqual("test user1", param.Name);
}
}
ReturnsDbSetの2つ目の引数にMock<DbSet<T>>
を渡すだけ。
このサンプルではAddメソッドをCallbackで上書きし、Addメソッドに渡された引数を退避する。
その後、退避した結果のプロパティが想定した結果となっているかを検証している。
ソースコードを見て解決したのだが、
And this is all. You can use your DbContext in your tests.
You will find examples of this library in the repository.
とか書かれていて、サンプルまであったので一生懸命サンプルの方を探してしまった。
気が向いたらプルリクエスト投げてみようかな。