2015-01-20 2 views
0

Я новичок в MOQ в C#. Вот мой код:Почему среда MOQ переопределяет все виртуальные методы - C#

public class CustomerBase 
    { 
     private List<Customer> customers = new List<Customer>(); 
     public const int MAX_CUSTOMERS = 100; 

     public int CustomerCount() 
     { 
      return customers.Count(); 
     } 

     public void AddCustomer(string name, string email) 
     { 
      if (CustomerCount() >= MAX_CUSTOMERS) 
      { 
       return; 
      } 
      Customer cus = new Customer(name); 
      customers.Add(cus); 
      SendEmail(email); 
     } 

     public virtual void SendEmail(string email) 
     { 
      throw new NotImplementedException(); 
     } 
    } 

    [TestClass] 
    public class UnitTest1 
    { 
     [TestMethod] 
     public void TestAddUser() 
     { 
      Mock<CustomerBase> m = new Mock<CustomerBase>(); 
      m.Setup(x => x.SendEmail("k")).Verifiable(); // bypass send email because email is server is not setup 
      m.Object.AddCustomer("max", "[email protected]"); 
      Assert.AreEqual(1, m.Object.CustomerCount()); 
     } 
    } 

тест проходит. Как только я делаю ClientCount виртуальным, тест терпит неудачу, потому что этот метод начинает возвращать ноль. Кто-нибудь знает, почему и как предотвратить такое поведение?


Обновленный код - с использованием внутренней сборки не удается:

[assembly: InternalsVisibleTo("UnitTestProject1")] // make the test assembly internal 
namespace MoqSmple1 
{ 
    public class CustomerBase 
    { 
     private List<Customer> customers = new List<Customer>(); 
     public const int MAX_CUSTOMERS = 100; 

     internal virtual int CustomerCount() 
     { 
      return customers.Count(); 
     } 

     public void AddCustomer(string name, string email) 
     { 
      if (CustomerCount() >= MAX_CUSTOMERS) 
      { 
       return; 
      } 
      Customer cus = new Customer(name); 
      customers.Add(cus); 
      SendEmail(email); 
     } 

     internal virtual void SendEmail(string email) 
     { 
      throw new NotImplementedException(); 
     } 
    } 
} 

namespace UnitTestProject1 
{ 
    [TestClass] 
    public class UnitTest1 
    { 
     [TestMethod] 
     public void TestAddUser() 
     { 
      Mock<CustomerBase> m = new Mock<CustomerBase>(); 
      m.Setup(x => x.SendEmail("k")).Verifiable(); // bypass send email because email is server is not setup 
      m.Object.AddCustomer("max", "[email protected]"); 
      m.CallBase = true;// keep the default behaviour of virtual methods except the ones skipped 
      Assert.AreEqual(1, m.Object.CustomerCount()); 
     } 
    } 
} 

обновление Я понял:

  • мне нужен открытый ключ
  • мне нужно сделать методы внутренние protected virtual

ответ

2

Вы хотите установить <YourMock>.CallBase = true. Here is a good article on CallBase

В двух словах Moq создаст прокси для всех виртуальных методов по умолчанию, а установка CallBase в true сохраняет реализацию по умолчанию, если вы явно не просите прокси.

+0

Спасибо. Если я могу задать следующий вопрос; использование MOQ требует, чтобы часть производственного кода была общедоступной виртуальной. Существуют ли какие-либо методы, чтобы избежать этого? – max

+1

Вы можете изменить их на внутренние виртуальные и использовать InternalsVisibleTo [TestAssembly]. Но в противном случае вам нужно использовать что-то более мощное (RhinoMocks) ... что приводит меня чаще к вопросу о дизайне в любом случае ... просто имейте это в виду –

+0

Спасибо @Jutin. Это отличный совет. – max

Смежные вопросы