Подтвердить что ты не робот

Как имитировать не виртуальные методы?

    [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 должен быть виртуальным, чтобы издеваться над ним. Есть ли способ обмануть не виртуальные методы?

4b9b3361

Ответ 1

Moq не может имитировать не виртуальные методы на классах. Либо используйте другие издевательские рамки, такие как Type mock Isolator, который фактически вставляет IL в вашу сборку или размещает интерфейс на EmailService и высмеивает это.

Ответ 2

Отказывание не виртуальных методов связано с использованием низкоуровневого API-интерфейса профилировщика. На данный момент я думаю, что доступны только следующие варианты:

оба являются коммерческими, даже если JustMock имеет облегченное издание, насмешливые не виртуальные методы доступны только с коммерческой версией. Как указано в комментариях, есть что-то от исследований Microsoft, в проекте Pex and Moles

Ответ 3

Альтернативой использованию виртуальных методов для издевательств является использование интерфейсов. Таким образом, вы можете издеваться над всей зависимостью.

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

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

Теперь вы можете создавать mocks интерфейса IEmailService, чтобы вы могли издеваться над любым из его методов. Разумеется, вам нужно будет изменить типы переменных, содержащих EmailService objects, на IEmailService, где это необходимо.

Ответ 4

Как @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);
    }

поскольку вы можете видеть, что созданный мной тест похож на те тесты, которые вы пытались создать.