1

我在基类上有一个用于管理列表项的通用方法:

public abstract class BaseViewModelHandler<T> : BaseLogger, IViewModelHandler<T>
    where T : IViewModel
{
    public abstract void Handle(T viewModel);

    protected ISet<TE> ManageListItems<TE>(int[] selectedItemIds, ISet<TE> list, IService<TE> service)
        where TE : IEntity
    {
        try
        {

... param checking and code to remove unwanted items not included for brevity

            if (selectedItemIds.Any())
            {
                var itemIdsToAdd = selectedItemIds.Where(id => list.All(x => x.Id != id)).ToList();
                if (itemIdsToAdd.Any())
                {
                    foreach (var id in itemIdsToAdd)
                    {
                        var item = service.GetById(id);
                        list.Add(item);
                    }
                }
            }

            return list;
        }

...catch block removed for brevity

    }
}

我有一个继承这个基类的类。

public class ConcreteViewModelHandler : BaseViewModelHandler<ConcreteViewModel>
{
    private readonly IMyService _myService;
    private readonly IMyListItemsService _myListItemsService

    public ConcreteViewModelHandler (IMyService myService, IMyListItemsService myListItemsService)
    {
        _myService = myService;
        _myListItemsService = myListItemsService
    }

    public override void Handle(ConcreteViewModel viewModel)
    {
        try
        {
            var myEntity = viewModel.Id.HasValue
                               ? _myService.GetById(viewModel.Id.Value)
                               : new MyEntity();

            myEntity.ListToManage = ManageListItems(viewModel.SelectedItemIds, myEntity.ListToManage, _myListItemsService);

...create/update removed for brevity

        }

...catch block removed for brevity

    }
}

我正在尝试测试 Handle 方法。在我的测试中,我模拟了服务,并设置了“GetById”方法以返回我的类的新实例

_myListItemsServiceMock = new Mock<IMyListItemsService>();
_myListItemsServiceMock
      .Setup(s => s.GetById(It.IsAny<int>()))
      .Returns(new MyListItem{ Id : 1});

我的测试没有通过,当我单步执行代码时,service.GetById(id); 基类中的调用返回 null。这是我正确使用 Moq 的第一个项目,所以我担心我对框架的缺乏经验会让我遗漏一些东西。

任何帮助将不胜感激。

根据要求添加TestFixture ...

[TestFixture]
public class ConcreteViewModelHandlerTestFixture
{
    private Mock<IMyService> _myServiceMock;
    private Mock<IMyListItemsService> _myListItemsServiceMock;

    #region Test Data

    private readonly ConcreteViewModel _viewModel = new ConcreteViewModel
    {
        Id = 1,
    };

    #endregion

    [SetUp]
    public void SetUp()
    {
        _myServiceMock = new Mock<IMyService>();
        _myServiceMock
            .Setup(s => s.GetById(It.IsAny<int>()))
            .Returns(new MyEntity { Id: 1});

        _myListItemsServiceMock = new Mock<IMyListItemsService>();
        _myListItemsServiceMock
            .Setup(s => s.GetById(It.IsAny<int>()))
            .Returns(new MyListItem{ Id : 1});
    }


    [Test]
    public void _the_handle_method_works()
    {
        //arrange
        var handler = new ConcreteViewModelHandler(_myServiceMock.Object, _myListItemsServiceMock.Object);

        // act
        handler.Handle(_viewModel);

        // assert
        // no assertions yet as the code falls over
    }
}

根据@Quinton Bernhardt 的要求添加更多细节

界面:

public interface IEntity
{
    int Id { get; }
    //Guid Guid { get; }
    int UpdateId { get; set; }
}

基类:

public abstract class BaseEntity : IEntity
{
    protected BaseEntity()
    {
    }

    protected BaseEntity(int id)
    {
        Id = id;
    }

    public virtual int Id { get; protected internal set; }
    public virtual int UpdateId { get; set; }
}

和 MyListItem 类

public class MyLIstitem : BaseEntity
{
    public MyLIstitem ()
    {
    }

    public MyLIstitem (int id)
        : base(id)
    {
    }


    public virtual string Name { get; set; }
    public virtual string Value { get; set; }
}
4

1 回答 1

1

您的问题描述说:

我的测试没有通过,当我单步执行对 service.GetById(id); 的调用时 在我的基类中返回 null。

所以肯定是调用ManageListItems<TE>()失败就行了:

var item = service.GetById(id);

希望我是正确的,因为这是一个假设[使用提供的信息]。

是否IMyListItemService实施IService<IEntity>?'因为你的代码暗示了它。

我能看到的唯一奇怪之处是 的最后一个参数ManageListItems<TE>()需要一个IService<TE> where TE is IEntity用于调用service.GetById(id).

protected ISet<TE> ManageListItems<TE>(int[] selectedItemIds, ISet<TE> list, IService<TE> service)

留在我身边……,以后有道理……

但是您从具体类中提供给该方法的对象是类型IMyListItemsService,从方法中的以下内容可以看出Handle

myEntity.ListToManage = ManageListItems(viewModel.SelectedItemIds, myEntity.ListToManage, _myListItemsService);

我认为正在发生的事情...您的设置GetById应该在IService而不是IMyListItemsService

在列表服务上设置 GetById 时,而不是这样:

    _myListItemsServiceMock
        .Setup(s => s.GetById(It.IsAny<int>()))
        .Returns(new IMyListItem{ Id : 1});

尝试

    _myListItemsServiceMock.As<IService>()
        .Setup(s => s.GetById(It.IsAny<int>()))
        .Returns(new IMyListItem{ Id : 1});

或者

    _myListItemsServiceMock.As<IService<IEntity>>()
        .Setup(s => s.GetById(It.IsAny<int>()))
        .Returns(new IMyListItem{ Id : 1});
于 2013-01-20T08:59:23.583 回答