[TestMethod]
public void TestMethod1()
{
var mock = new Mock<EmailService>();
mock.Setup(x => x.SendEmail()).Returns(true);
var cus = new Customer();
var result = cus.AddCustomer(mock.Object);
Assert.IsTrue(result);
}
public class Customer
{
public bool AddCustomer(EmailService emailService)
{
emailService.SendEmail();
Debug.WriteLine("new customer added");
return true;
}
}
public class EmailService
{
public virtual bool SendEmail()
{
throw new Exception("send email failed cuz bla bla bla");
}
}
EmailService.SendEmail
メソッドは、モックするために仮想でなければなりません。非仮想メソッドをモックする方法はありますか?
Moqはクラスの非仮想メソッドをモックできません。実際にILをアセンブリに織り込む Type mock Isolator などの他のモックフレームワークを使用するか、EmailService
にインターフェイスを配置してモックします。
非仮想メソッドのモックには、低レベルのプロファイラーAPIの使用が含まれます。現時点では、利用できるオプションは次のとおりです。
どちらも商用版です。たとえJustMockにライトエディションが含まれていても、商用版でモッキング以外の仮想メソッドを使用できます。コメントで指摘したように、プロジェクトにはマイクロソフトの調査によるものがあります Pex and Moles
モックに仮想メソッドを使用する代わりに、インターフェイスを使用します。これにより、依存関係全体をモックアウトできます。
public interface IEmailService
{
bool SendEmail();
// etc...
}
public class EmailService : IEmailService
{
//...
}
インターフェイスIEmailService
のモックを作成して、そのメソッドをモックできるようになりました。もちろん、必要に応じて、EmailService
オブジェクトを含む変数のタイプをIEmailService
に変更する必要があります。
pose
を使用します。静的または非仮想を含む任意のメソッドを置き換えることができます。かなり新しいプロジェクトですが、完全にオープンソースMITライセンス。 https://github.com/tonerdo/pose
Typemock Isolator を使用するときに@aqwertと@Feliceが書いたように、コードを追加または変更せずに非仮想メソッドをモックすることが可能です(非常に簡単です)。
[TestMethod,Isolated]
public void TestMethod1()
{
var mock = Isolate.Fake.Instance<EmailService>();
Isolate.WhenCalled(() => mock.SendEmail()).WillReturn(true);
var cust = new Customer();
var result = cust.AddCustomer(mock);
Assert.IsTrue(result);
}
作成したテストは、作成しようとしたテストに似ています。
非仮想メソッドをモックする唯一の方法は、そのクラスを非仮想メソッドで実装するために使用されるインターフェースをモックすることです。以下に例を示します。
public interface IEmployee
{
DateTime GetDateofJoining(int id);
}
public class Employee
{
public DateTime GetDateofJoining(int id)
{
return DateTime.Now;
}
}
public class Program
{
static void Main(string[] args)
{
var employee = new Mock<IEmployee>();
employee.Setup(x => x.GetDateofJoining(It.IsAny<int>())).Returns((int x) => DateTime.Now);
Console.WriteLine(employee.Object.GetDateofJoining(1));
Console.ReadLine();
}
}