0

I have a simple functional style test for output of a command that I've written using Mediatr's IRequest and IRequestHandler<>

[Fact]
public void TestReturnValuesAsync()
{
    // Arrange
    var handler = new Mock<IRequestHandler<SyncSubmerchantDataCommand, CommandResult<int>>>();
    handler.Setup(x => x.Handle(It.IsAny<SyncSubmerchantDataCommand>(), It.IsAny<CancellationToken>())).ReturnsAsync(new CommandResult<int>(0, ResultStatus.Success, "string"));

    // Act
    var result = handler.Object.Handle(new SyncSubmerchantDataCommand(), new CancellationToken());

    // Assert
    result.Result.Data.ShouldBe(0);
    result.Result.Status.ShouldBe(ResultStatus.Success);
    result.Result.Message.ShouldBe("string");
}

Since this command runs as a background task, I don't want it interrupted. I have a variable, submerchantList, that is of type List<T> which is used in a foreach loop to do work. The work is set in a try-catch because I don't want the command interrupted, as I stated before. I want to test the output of the what is written to my logs (_log.info) if an exception is thrown during this process.

public class CommandNameHandler : IRequestHandler<source, destination> {
    // constructors and privates
    public async destination Handle(param, token)
    {
        var submerchantList = db call.ToList();
        foreach (var item in submerchantList)
        {
            try {
                //does work
            }
            catch (Exception e) {
               if (item != null)
                   _log.info($"{e} - {item.Id}");
            }
            return some out put
        }

The problem is that I can't seem to figure out how to set the value of the any variable, such as the submerchantList within the Handle in order to throw the exception for my next test. I'm stumped.

Any help would be greatly appreciated.

SOLUTION:

Here was the solution: Stubbing the database call by injecting an in-memory DbSet. I used this resource learn.microsoft.com/en-us/ef/ef6/fundamentals/testing/… This issue was db call.ToList It looked something like this _db.Table.Include(x => x.Foreign).Where(x => x.Foreign.Field == Enum.Value).ToListAsync() While I was setting up the Mock DbSet, I had to use the string version, not the LINQ-chain version in the unit test. So, that means mockDbset.Setup(x => x.Table.Include("Foreign")).Returns(myCustomDbSet); Hope that helps someone!

CSharpMinor
  • 202
  • 1
  • 9
  • You can stub `"db call".ToList()` – mxmissile Jan 04 '19 at 15:25
  • @mxmissile That's what I'd like to do, but I'm having trouble accessing it, whether I mock the command or new it up, the only option it seems I have is to setup the handle, but nothing within the handle. – CSharpMinor Jan 04 '19 at 15:31
  • Inject your db in the handler's constructor. Stub the "call". – mxmissile Jan 04 '19 at 15:48
  • @mxmissile if I understand this correctly you're saying: `var db = new Mock();` `db.Setup(x => x.Entity).Returns(new Entity { //data});` `await CommandHandler(db.Object);` right? Sorry running slow this morning. – CSharpMinor Jan 04 '19 at 15:52
  • 1
    https://gist.github.com/mxmissile/4df25560a2643d6a52702a3206675233 – mxmissile Jan 04 '19 at 16:04
  • Oh I see now. I'll have to refactor for an interface for my dbcontext. – CSharpMinor Jan 04 '19 at 16:40
  • Still no success on this. I can sucessfully mock a dbset and inject that into the passed handler for my db context. the problem I have now is in my command query. The command returns null for any data returned with an .Include(x => x.Whatever) in the linq query. – CSharpMinor Jan 07 '19 at 15:19
  • Here was the solution: Stubbing the database call by injecting an in-memory DbSet. I used this resource https://learn.microsoft.com/en-us/ef/ef6/fundamentals/testing/mocking#testing-query-scenarios This issue was 'db call.ToList' It looked something like this `_db.Table.Include(x => x.Foreign).Where(x => x.Foreign.Field == Enum.Value).ToListAsync()` While I was setting up the Mock DbSet, I had to use the string version, not the LINQ version in the unit test. So, that means `mockDbset.Setup(x => x.Table.Include("Foreign")).Returns(myCustomDbSet);` Hope that helps someone! – CSharpMinor Jan 08 '19 at 16:12
  • 1
    @CSharpMinor you should actually add [that](https://stackoverflow.com/questions/54041530/how-does-one-set-a-variable-in-a-command-using-mediatr-with-moq#comment95023754_54041530) as a self answer to you question. Others would find it easier if it was an answer rather than in the comments. – Nkosi Jan 21 '19 at 23:22

0 Answers0