2012-07-31 151 views
21
[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方法必須虛擬來模擬它。有什麼辦法來模擬非虛擬方法嗎?如何模擬非虛擬方法?

回答

16

Moq無法模擬類上的非虛擬方法。可以使用其他模擬框架,如Type mock Isolator,它們實際上將IL編織到您的程序集中,或者將接口放在EmailService上,然後模擬它。

4

必須使用虛擬方法進行模擬的替代方法是使用接口。這樣你可以嘲笑整個依賴。現在

public interface IEmailService 
{ 
    bool SendEmail(); 
    // etc... 
} 

public class EmailService : IEmailService 
{ 
    //... 
} 

您可以創建界面IEmailService的嘲笑,讓你嘲笑它的任何方法。當然,您必須在適當的情況下將包含EmailService對象的變量類型更改爲IEmailService

+0

我認爲使用這種技術很好,而且使用接口肯定有優勢。但是如果你在兩種選擇之間評估非虛擬方法是可嘲弄的:1)使其成爲虛擬的,2)將它用作接口的一部分,2的優勢是什麼?即使你選擇了2,那麼你也有效地使該方法成爲虛擬的,因爲它現在成爲界面的一部分。 – zumalifeguard 2015-06-25 17:10:40

7

模擬非虛擬方法涉及使用低級別探查器API。此刻,我覺得唯一可用的選項是:

都是商業的,即使JustMock有精簡版版,嘲諷非虛方法可正好與商業版。 正如在評論中指出有一些來自微軟的研究,在項目Pex and Moles

+5

我認爲你可以添加微軟鼴鼠/ Pex/Fakes到該列表。作爲獎勵,它是免費的。 – podiluska 2012-07-31 10:43:08

+0

假貨不包含在VS的快遞版本中。 – 2015-08-19 23:30:00

1

由於@aqwert和@Felice使用Typemock Isolator它是可能的(很容易),當嘲笑沒有添加或更改任何代碼非虛方法寫,例如:

[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); 
    } 

正如您所看到的我創建的測試與您嘗試創建的測試類似。