moq を使っていて、ハマったことがあったので備忘録として残しておきます。
主題の通り、「moq で virtual メソッドをコールする方法」です。
やりたかったことと症状
以下のような Dispose パターンを使用したテスト対象のクラスがあったとします。
public class abstract BaseClass : IDisposable
{
protected virtual void Dispose(bool disposing)
{
if(disposing) DisposeCore();
}
abstract void DisposeCore();
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
DisposeCore
メソッドをモックして、Dispose()
実行時にモックした DisposeCore
が呼ばれることをテストしようとした際、virtual な Dispose(bool)
がコールされる必要があります。
おそらくコードとしては以下の感じでしょうか。
[Fact]
public void DisposeTest()
{
var mock = new Mock<BaseClass>();
mock.Protected().Setup("Dispose", ItExpr.IsAny<bool>()).Callback(()=> /*何かのテスト処理*/);
mock.Object.Dispose();
}
しかし、このままでは Dispose()
内部でコールされるはずの virtual Dispose(bool)
が実行されないのです。
原因と解決方法
原因は、デフォルトでは moq は virtual メソッドは実行されないからっぽいです。
ここまでは、実際の動作からしてそうなんだろうと予想はつくのですが、いかんせん対策方法がわかりません。
で、検索すると、英語版の StackOverflow にまんま答えがありました。
以下の通りフラグを立ててやればよいらしいです。
[Fact]
public void DisposeTest()
{
var mock = new Mock<BaseClass>();
mock.Protected().Setup("Dispose", ItExpr.IsAny<bool>()).Callback(()=> /*何かのテスト処理*/);
mock.CallBase = true; // <- これ!!
mock.Object.Dispose();
}
実際にこれで、virtual Dispose(bool)
がコールされました。
コメント