Мой контекст - это макет моей модели данных. У меня есть метод «Отправить» в другом классе с именем «Электронная почта». Мой класс обслуживания использует макетированную модель данных.Метод в моем классе обслуживания «SendEmailForAlarm» получает доступ к данным из модели данных Mock, а затем вызывает метод «Отправить» в классе электронной почты.Вопрос: Как я могу получить метод «Отправить» в своем классе электронной почты для включения в мою макет?
Код восстановления:
//INTERFACES
public interface IEmail
{
...
void Send(string from, string to, string subject, string body, bool isHtml = false);
}
public interface IEntityModel : IDisposable
{
...
DbSet<Alarm> Alarms { get; set; } // Alarms
}
//CLASSES
public class Email : IEmail
{
...
public void Send(string from, string to, string subject, string body, bool isHtml = false)
{
...sends the email
}
}
public partial class EntityModel : DbContext, IEntityModel
{
...
public virtual DbSet<Alarm> Alarms { get; set; } // Alarms
}
public class ExampleService : ExampleServiceBase
{
//Constructor
public ExampleService(IEntityModel model) : base(model) { }
...
public void SendEmailForAlarm(string email, Alarm alarm)
{
...
new Email().Send(from, to, subject, body, true);
}
}
//HELPER method
public static Mock<DbSet<T>> GetMockQueryable<T>(Mock<DbSet<T>> mockSet, IQueryable<T> mockedList) where T : BaseEntity
{
mockSet.As<IQueryable<T>>().Setup(m => m.Expression).Returns(mockedList.Expression);
mockSet.As<IQueryable<T>>().Setup(m => m.ElementType).Returns(mockedList.ElementType);
mockSet.As<IQueryable<T>>().Setup(m => m.GetEnumerator()).Returns(mockedList.GetEnumerator());
mockSet.Setup(m => m.Include(It.IsAny<string>())).Returns(mockSet.Object);
// for async operations
mockSet.As<IDbAsyncEnumerable<T>>()
.Setup(m => m.GetAsyncEnumerator())
.Returns(new TestDbAsyncEnumerator<T>(mockedList.GetEnumerator()));
mockSet.As<IQueryable<T>>()
.Setup(m => m.Provider)
.Returns(new TestDbAsyncQueryProvider<T>(mockedList.Provider));
return mockSet;
}
Следующий модульный тест проходит, но не записывается вПодтверждение того, что электронная почта была действительно отправлена (или вызвана) Метод service.SendEmailForAlarm запрашивает DBSet EntityModel.Alarms и извлекает информацию из полученного объекта.Затем он вызывает метод Send в классе электронной почты и возвращает void.
[TestMethod]
public void CurrentTest()
{
//Data
var alarms = new List<Alarm> {CreateAlarmObject()} //create a list of alarm objects
//Arrange
var mockContext = new Mock<IEntityModel>();
var mockSetAlarm = new Mock<DbSet<Alarm>>();
var service = new ExampleService(mockContext.Object);
mockSetAlarm = GetMockQueryable(mockSetAlarm, alarms.AsQueryable());
mockContext.Setup(a => a.Alarms).Returns(mockSetAlarm.Object);
//Action
service.SendEmailForAlarm("test@domain.com", alarms[0]);
//NOTHING IS ASSERTED, SendEmailForAlarm is void so nothing returned.
}
Что я хотел бы сделать, так это поместить перехватчик в метод Email.Send, чтобы я мог подсчитать, сколько раз он был выполнен илииметь mock verify validate он вызывался n раз (в этом примере один раз).
[TestMethod]
public void WhatIWantTest()
{
//Data
var alarms = new List<Alarm> {CreateAlarmObject()} //create a list of alarm objects
var calls = 0;
//Arrange
var mockEmail = new Mock<IEmail>(); //NEW
var mockContext = new Mock<IEntityModel>();
var mockSetAlarm = new Mock<DbSet<Alarm>>();
var service = new ExampleService(mockContext.Object);
mockEmail.Setup(u =>
u.Send(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(),
It.IsAny<string>(), It.IsAny<bool>()))
.Callback(() => calls++); //NEW add a call back on the Email.Send method
mockSetAlarm = GetMockQueryable(mockSetAlarm, alarms.AsQueryable());
mockContext.Setup(a => a.Alarms).Returns(mockSetAlarm.Object);
//Action
service.SendEmailForAlarm("test@domain.com", alarms[0]);
//Assert NEW
Assert.AreEqual(1, calls); //Check callback count to verify send was executed
//OR
//Get rid of method interceptor line above and just verify mock object.
mockEmail.Verify(m => m.Send(It.IsAny<string>(), It.IsAny<string>(),
It.IsAny<string>(), It.IsAny<string>(),
It.IsAny<bool>()), Times.Once());
}
Когда я запускаю это, Assert завершается неудачно для "Calls" = 0 и Times.Once также равно нулю.Я считаю, что моя проблема связана с тем, что «сервис» был создан с использованием «mockContext» (IEntityModel), который необходим для доступа к данным тревоги, но метод Send не является частью mockContext.Если я создаю макет «mockEmail» и добавляю свой обратный вызов, я не могу понять, как добавить его в mockContext.
Как я могу добавить оба Mock IEmail И Mock IEntityModel в тот же контекст, или я собираюсь об этом всенеправильно?