0

I am using Mass Transit, Entity Framework, C# in my project.

I have my consumer consuming an event and which insert data in to the table. I would like to know how to mock the consumer and unit test case for this method.

public async Task Consume(ConsumeContext<MyEvent> context)
{
    private readonly MyDbContext _dbContext;  

    try
    {
        // Here logic to insert record in to new database
        var data = new MyService.TableNmae()
        {
            
            Id = context.Message.MyId,
            Description = "test data"
        };

        _ = _dbContext.TableName.AddAsync(data);
        _ = _dbContext.SaveChangesAsync(context.CancellationToken);
    }
    catch (Exception ex)
    {
        _logger.LogCritical($"{GetType().Name}:{nameof(Consume)} {ex}");
    }

    await Task.CompletedTask;
}

Here is my unit test case code i have added

{ private ITestHarness _testHarness;

[SetUp]
public void Initialize()
{
    var serviceCollection = new ServiceCollection();

    serviceCollection.AddMassTransitTestHarness(busRegistrationConfigurator =>
    {
        busRegistrationConfigurator.AddConsumer<MyConsumer>();
    });

    var serviceProvider = serviceCollection.BuildServiceProvider();

    _testHarness = serviceProvider.GetRequiredService<ITestHarness>();
}


[Test]

public async Task TestMethod1()
{
    await _testHarness.Start();
    await _testHarness.Bus.Publish(new MyEvent { Code = "H"});

    Assert.That(await _testHarness.Published.Any<MyEvent>(), Is.True);
    Assert.That(await _testHarness.Consumed.Any<MyEvent>(), Is.True);
}

}

Expected: True But was: False.

Here the first assert is true but second assert always false,

chris R
  • 1
  • 1
  • 1
    `entity-framework` is not `entity-framework-core`, please correct your tags – Stefan Wuebbe Feb 01 '23 at 09:35
  • Use a mock DB context, add the data, verify that the data exists. This answer should point you in the right direction https://stackoverflow.com/questions/32793747/how-to-moq-entity-framework-savechangesasync – Aaron Feb 01 '23 at 09:35
  • There's no reason to test `SaveChangesAsync`. It works. If you want to test whether saving worked 1) this code never awaits the operations, so it's broken outright 2) you can use the in-memory or SQLite provider and then check whether anything was written. `AddAsync` isn't needed to begin with and probably points to a misunderstanding of EF and ORMs in general: `Add` doesn't add anything to the database. It tells DbContext to start tracking an object *and all relations* in the `Added` state. EF Core deals with Entities, not Tables That's not nitpicking – Panagiotis Kanavos Feb 01 '23 at 11:10
  • ORMs like EF Core are trying to give the impression of working with in-memory *entities*, not database tables. There are `Event` objects, not an Events table. A DbContext is essentially a disconnected Unit-of-Work. It tracks all entities loaded through it (or attached with Add, Update) but doesn't save anything. At the very end of the UoW/domain transaction, `SaveChanges` is called to save all those changes in a single database transaction. If not called, the changes are discarded when it's disposed. A DbContext doesn't even keep a connection to the database, it only opens one to load or save – Panagiotis Kanavos Feb 01 '23 at 11:13

1 Answers1

1

Instead of trying to mock ConsumeContext<T>, I recommend using the MassTransit test harness, which is documented on the web site.

As others have pointed out, testing simply that your entity was saved is a pretty trivial test, and more of an integration test assuming you are verifying that the entity was saving all required properties, etc. Not something I would test in isolation, vs. ensuring the data is available for higher level operations being tested.

Chris Patterson
  • 28,659
  • 3
  • 47
  • 59
  • i have edited my unit test case with what i have done so far. I am sure i am making some mistake somewhere – chris R Feb 01 '23 at 13:02
  • it looks like i am missing something in my setup – chris R Feb 01 '23 at 13:37
  • verify should be after you've awaited the Consumed so that the consumer has had time to do its work. You also don't need to mock `ILogger` as MassTransit adds one with the test harness. – Chris Patterson Feb 01 '23 at 14:14
  • I have changed it, but still get the same – chris R Feb 01 '23 at 18:08
  • here my consumer just listen an event and does only insertion to database. – chris R Feb 02 '23 at 06:48
  • the sampe sample provided involves a request and response. Can you show me a a consumer where a request and resoponse not involved.Had edited my test case as well..here the second asset always gives false – chris R Feb 02 '23 at 09:39