I am trying to run unit tests using Moq. I am fairly new to Moq and I have ran into a problem with this current unit test.
I have a controller that is fetching some items. The result is encapsulated within a generic interface using ICollection
.
public interface IResult
{
}
public interface IListResult : ICollection<IResult>
{
}
My controller is simply calling a method that returns the result.
[HttpGet("get/{userId}/{pageSize}/{fetchNext}")]
public IActionResult GetConversations(int userId, int pageSize, bool fetchNext)
{
try
{
GetConversationsByUserIdQuery query = new GetConversationsByUserIdQuery()
{
UserId = userId,
PageSize = pageSize,
FetchNext = fetchNext
};
var result = _mediator.GetConversationsByUserId(query);
return Ok(result);
}
catch (Exception ex)
{
return StatusCode(StatusCodes.Status500InternalServerError, ex.Message);
}
}
}
When I am running my unit test, the result always comes back null and I am failing to understand what I am missing in my set up.
[Theory]
[InlineData(1, 2 , false)]
[InlineData(1, 2 , true)]
public async void When_AddMessageToNewConversation_ThenSuccessfullyAdd(int userId, int pageSize, bool fetchNext)
{
// Arrange
Mock<IMessageMediator> _mediator = new Mock<IMessageMediator>();
Mock<IListResult> _listResult = new Mock<IListResult>();
GetConversationsByUserIdQuery query = new GetConversationsByUserIdQuery()
{
UserId = userId,
PageSize = pageSize,
FetchNext = fetchNext
};
List<Conversation> expected = new List<Conversation>()
{
new Conversation()
{
Id = Guid.NewGuid(),
Created_At = DateTimeOffset.Now
}
};
_listResult.Setup(x =>
x.GetEnumerator())
.Returns(expected.GetEnumerator());
GetConversationsByUserIdController controller = new GetConversationsByUserIdController(_mediator.Object);
_mediator.Setup(x =>
x.GetConversationsByUserId(query)).Returns(_listResult.Object);
// Act
IActionResult result = controller.GetConversations(userId, pageSize, fetchNext);
// Assert
Assert.True(result is OkResult);
}
The IMessageMediator is simply a delegator that handles implementation of queriers and commands. The IListResult is returned from a querier handler.
public class GetConversationsByUserIdQueryHandler:
IQueryHandler<GetConversationsByUserIdQuery>
{
private IRepository<Conversations_By_UserId>
_conversationByUserIdRepository;
private IListResult _result;
public GetConversationsByUserIdQueryHandler(IRepository<Conversations_By_UserId> conversationByUserIdRepository,
IListResult result)
{
_conversationByUserIdRepository = conversationByUserIdRepository;
_result = result;
}
public IListResult Handle(GetConversationsByUserIdQuery query)
{
IEnumerable<Conversations_By_UserId> conversations = _conversationByUserIdRepository
.Get(query.PageSize,
query.FetchNext,
message => message.UserId == query.UserId).ToList();
if (conversations.Any())
{
foreach (Conversations_By_UserId m in conversations)
{
_result.Add(new Conversation()
{
Created_At = m.Created_At,
Id = m.Id,
});
}
}
return _result;
}
}
CodePudding user response:
You don't need to mock both IMessageMediator
and IListResult
.
You should mock dependencies - it is IMessageMediator
in your case - and your can setup it to return any result.
The other thing - you mock _mediator
using query created in test, but in controller you create different query (references are different) and it is the reason of null
result.
Change your test:
[Theory]
[InlineData(1, 2 , false)]
[InlineData(1, 2 , true)]
public async void When_AddMessageToNewConversation_ThenSuccessfullyAdd(int userId, int pageSize, bool fetchNext)
{
// Arrange
Mock<IMessageMediator> _mediator = new Mock<IMessageMediator>();
List<Conversation> expected = new List<Conversation>()
{
new Conversation()
{
Id = Guid.NewGuid(),
Created_At = DateTimeOffset.Now
}
};
GetConversationsByUserIdController controller = new GetConversationsByUserIdController(_mediator.Object);
// It.IsAny<GetConversationsByUserIdQuery>()) instead of query
_mediator.Setup(x => x.GetConversationsByUserId(It.IsAny<GetConversationsByUserIdQuery>()))
// create fake result to return from mediator (no need to mock IListResult
.Returns(new ListResult() ...); // just create instance of IListResult with needed values
// Act
IActionResult result = controller.GetConversations(userId, pageSize, fetchNext);
// Assert
Assert.True(result is OkResult);
}