[TestMethod] public void TestMethod1() { var mock = new Mock(); 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"); } }
El método EmailService.SendEmail
debe ser virtual para EmailService.SendEmail
. ¿Hay alguna forma de burlarse de los métodos no virtuales?
Moq no puede burlarse de los métodos no virtuales en las clases. Utilice otros marcos de burla como el aislador tipo simulacro que realmente teje IL en su conjunto o coloque una interfaz en EmailService
y EmailService
eso.
Burlarse de métodos no virtuales implica el uso de API de perfil de bajo nivel. Por el momento, creo que las únicas opciones disponibles son:
ambos son comerciales, incluso si JustMock tiene una edición lite, métodos virtuales no burladores están disponibles solo con la versión comercial. Como se señala en los comentarios, hay algo de investigación de Microsoft, en el proyecto Pex y Moles
La alternativa a tener que usar métodos virtuales para burlarse es usar interfaces. De esta forma puedes burlar una dependencia completa.
public interface IEmailService { bool SendEmail(); // etc... } public class EmailService : IEmailService { //... }
Ahora puede crear IEmailService
de la interfaz IEmailService
para permitirle burlarse de cualquiera de sus métodos. Por supuesto, deberá cambiar los tipos de variables que contienen objetos IEmailService
a IEmailService
corresponda.
Como @aqwert y @Felice escribieron al usar Typemock Isolator , es posible (y bastante fácil) simular métodos no virtuales sin agregar o cambiar ningún código, por ejemplo:
[TestMethod,Isolated] public void TestMethod1() { var mock = Isolate.Fake.Instance(); Isolate.WhenCalled(() => mock.SendEmail()).WillReturn(true); var cust = new Customer(); var result = cust.AddCustomer(mock); Assert.IsTrue(result); }
como puede ver, la prueba que he creado es similar a la prueba que intentó crear.
Usa pose
Le permite reemplazar cualquier método, incluso estático o no virtual. Proyecto bastante nuevo, pero con licencia MIT de fuente completamente abierta. https://github.com/tonerdo/pose
La única forma de simular métodos no virtuales es simular la interfaz utilizada para implementar esa clase con métodos no virtuales. A continuación está el ejemplo.
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(); employee.Setup(x => x.GetDateofJoining(It.IsAny())).Returns((int x) => DateTime.Now); Console.WriteLine(employee.Object.GetDateofJoining(1)); Console.ReadLine(); } }