tomasfabian / ksqlDB.RestApi.Client-DotNet

ksqlDb.RestApi.Client is a C# LINQ-enabled client API for issuing and consuming ksqlDB push and pull queries and executing statements.
MIT License
93 stars 24 forks source link

Unit Testability - Question #2

Closed HaroonSaid closed 2 years ago

HaroonSaid commented 2 years ago

Hi

I have a very simple class that I want a unit test, do you have any example of how mock

public class KSqlDb : IRepostory
    {
        private readonly ILogger<KSqlDb> logger;
        private readonly KSqlDbOptions options;
        private readonly IKSqlDBContext context;
        public KSqlDb(IOptions<KSqlDbOptions> options, IKSqlDBContext context, ILogger<KSqlDb> logger)
        {
            this.context = context;
            this.logger = logger;
            this.options = options.Value;
        }
        public async Task<ElasticSearchEvent> GetById(long contextId, long id)
        {
              var response = await this.context.CreatePullQuery<ElasticSearchEvent>(this.options.EventTopic)
             .Where(c => c.Key == Helpers.CreateKey(contextId, id))
             .GetAsync();
            return response;
        }

Can you give any guidance on how to mock IKSqlDBContext and IPullQuery?

tomasfabian commented 2 years ago

Hi @HaroonSaid, I recommend you use an isolation framework like Moq to mock your external dependencies:

Install-Package Moq

You can mock IKSqlDBContext.CreatePullQuery in the following way, it is a little bit more involved, but you can generalize it:

  [TestClass]
  public class KSqlDbTests
  {
    [TestMethod]
    public async Task GetById()
    {
      //Arrange
      var ksqlDbContextMock = new Mock<IKSqlDBContext>();
      var pullQueryMock = new Mock<IPullable<ElasticSearchEvent>>();
      var pullQueryProviderMock = new Mock<IPullQueryProvider>();

      pullQueryProviderMock.Setup(c => c.CreateQuery<ElasticSearchEvent>(It.IsAny<Expression>()))
        .Returns(pullQueryMock.Object);

      pullQueryMock.Setup(c => c.Provider)
        .Returns(pullQueryProviderMock.Object);

      pullQueryMock.Setup(c => c.Expression)
        .Returns(Expression.Constant(pullQueryMock.Object));

      pullQueryMock.Setup(c => c.GetAsync(It.IsAny<CancellationToken>()))
        .ReturnsAsync(new ElasticSearchEvent { Key = 42 });

      ksqlDbContextMock.Setup(c => c.CreatePullQuery<ElasticSearchEvent>("EventTopic"))
        .Returns(pullQueryMock.Object);

      var classUnderTest = new KSqlDb(ksqlDbContextMock.Object);

      //Act
      var elasticSearchEvent = await classUnderTest.GetById(contextId: 1, id: 12);

      //Assert
      Assert.AreEqual(42, elasticSearchEvent.Key);
    }
}
tomasfabian commented 2 years ago

I also added a push query test example:

https://github.com/tomasfabian/Kafka.DotNet.ksqlDB/wiki/How-to-mock-IKSqlDbContext

Was this useful?

tomasfabian commented 2 years ago

@HaroonSaid have you been able to test your code with mocked IKSqlDBContext as I suggested you?

Can we close the issue (question)?

HaroonSaid commented 2 years ago

Yes - thank you

tomasfabian commented 2 years ago

You are welcome.