I have a generic method on a base class for managing list items:
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
}
}
I have a class that inherits this base class.
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
}
}
I am trying to test the Handle method. In my test I mock the service, and I setup the ‘GetById’ method to return a new instance of my class
_myListItemsServiceMock = new Mock<IMyListItemsService>();
_myListItemsServiceMock
.Setup(s => s.GetById(It.IsAny<int>()))
.Returns(new MyListItem{ Id : 1});
My test does not pass, when I step through the code the call to service.GetById(id); in my base class returns null. This is the first project on which I have used Moq properly so I fear my inexperience with the framework has me missing something.
Any help would be greatly appreciated.
As requested adding the 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
}
}
Adding more detail as requested by @Quinton Bernhardt
interface:
public interface IEntity
{
int Id { get; }
//Guid Guid { get; }
int UpdateId { get; set; }
}
base class:
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; }
}
and the MyListItem class
public class MyLIstitem : BaseEntity
{
public MyLIstitem ()
{
}
public MyLIstitem (int id)
: base(id)
{
}
public virtual string Name { get; set; }
public virtual string Value { get; set; }
}
Your problem description says:
So it must be the call to
ManageListItems<TE>()that fails on the line:Hopefully i’m correct as it’s an assumption [using the information provided].
Does
IMyListItemServiceimplementIService<IEntity>? ‘cos your code implies it.The only weirdness i can see is that the last parameter of
ManageListItems<TE>()expects a parameter of typeIService<TE> where TE is IEntitywhich is used to make the call toservice.GetById(id).stay with me…, it makes sense later on…
But the object you supply to that method from your concrete class is of type
IMyListItemsServiceas can be seen from the following in theHandlemethod:what i think is happening… your setup of
GetByIdshould be on theIServiceinstead of theIMyListItemsServiceWhen setting up the GetById on the on the list service, instead of this:
try
or