【问题标题】:C# mocking generic repository using MoqC#使用MOQ模拟通用存储库
【发布时间】:2018-06-28 12:44:46
【问题描述】:

我已经在我的项目中实现了通用存储库。现在我正在为我的消费者编写测试用例。我正在尝试通过 Moq 模拟数据库功能,但我从数据库中获取值,而不是我通过 Moq 伪造的值。下面我分享我的实现。希望有人能帮我指出我犯的错误。

我的界面:

public interface IEventsRepository<T> : IRepository<T>  {

T GetEventsByEventId(int eventId);  }

我的班级:

public class EventsTableRepository : EFDBRepository<EventsModel>, IEventsRepository<EventsModel>  {
public EventsModel GetEventsByEventId(int eventId)
{
  return _dbSet.Where(x => x.EventID == eventId).FirstOrDefault();
}

}

我的消费者:

public static Response<string> EventsAccept(EventsAlertsRequest logMsgId)
{
  IEventsRepository<EventsModel> eventsRepo = (IEventsRepository<EventsModel>)RepositoryLocator.GetRepositoryObject(STMEnums.RepositoryName.EventsTableRepository.ToString());
  EventsModel eventmodel = new EventsModel();
  eventmodel = eventsRepo.GetEventsByEventId(eachlogMsgId);
  return EventStatusChangeResponse;
}

测试方法:

public void EventsAcceptSuccessTest()
    {
        EventsModel eventmodel = new EventsModel();
        eventmodel.Message = "TEST";

        Mock<IEventsRepository<EventsModel>> obj = new Mock<IEventsRepository<EventsModel>>();
        obj.Setup(m => m.GetEventsByEventId(Moq.It.IsAny<int>())).Returns(eventmodel);

        EventStatusChangeResponse = Diagnostics_.EventsAccept(logMsgId);            
        Assert.AreEqual(eventmodel.Status, EventStatus.ACCEPTED);
    }

【问题讨论】:

    标签: c# unit-testing generics moq


    【解决方案1】:

    在所提供的示例中,没有将模拟注入到被测对象的位置。此外,测试中的主题方法似乎正在使用静态服务定位器反模式来获得所需的模型。 这里做一个假设,因为类的其余部分没有显示与该变量的关系。

    定位器必须是一个注入的抽象,以便有机会模拟其预期行为

    public class Consumer {
        private IRepositoryLocator RepositoryLocator;
    
        public Consumer(IRepositoryLocator RepositoryLocator) {
            this.RepositoryLocator = RepositoryLocator;
        }
    
        public Response<string> EventsAccept(EventsAlertsRequest logMsgId) {
          IEventsRepository<EventsModel> eventsRepo = (IEventsRepository<EventsModel>)RepositoryLocator.GetRepositoryObject(STMEnums.RepositoryName.EventsTableRepository.ToString());
          EventsModel eventmodel = new EventsModel();
          eventmodel = eventsRepo.GetEventsByEventId(eachlogMsgId);
          return EventStatusChangeResponse;
        }
    }
    

    这意味着定位器也必须被正确地模拟才能完成测试。

    public void EventsAcceptSuccessTest() {
        //Arrange
        var eventmodel = new EventsModel() {
            Message = "TEST"
        };
    
        var repositoryMock = new Mock<IEventsRepository<EventsModel>>();
        repositoryMock
            .Setup(_ => _.GetEventsByEventId(It.IsAny<int>()))
            .Callback((int id) => {
                eventmodel.EventID = id;
                eventmodel.Status = EventStatus.ACCEPTED;
            })
            .Returns(eventmodel);
    
        var locatorMock = new Mock<IRepositoryLocator>();
        locatorMock.Setup(_ => _.GetRepositoryObject(It.IsAny<string>())).Returns(repositoryMock.Object);
    
        var subject = new Consumer(locatorMock.Object);
    
        //Act
        var response = subject.EventsAccept(logMsgId);
    
        //Assert
        Assert.AreEqual(eventmodel.Status, EventStatus.ACCEPTED);
    }
    

    【讨论】:

    • 有效@nkosi 你能帮我理解'.Callback'的东西吗?它有什么作用以及为什么我必须使用它?
    • @user3891367 我忘了在答案中包含参考Moq Quickstart。您应该查看它以更好地理解该模拟框架。
    • @user3891367 基于您所需的断言,这意味着在调用被测方法后需要更新模型。回调允许在调用模拟方法之后发生这种情况。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-08
    • 2011-05-27
    • 1970-01-01
    • 2011-05-27
    • 2023-03-28
    相关资源
    最近更新 更多