0

Within Startup I have defined a factory, something similar to How to register multiple implementations of the same interface in Asp.Net Core?

Interface has 1 method Process as below.

//saves to db.
public interface Iprocessor
{
   void Process(List<items>);
}

Code to register factory within the Startup.cs

Func<string, IProcessor> accessor = key =>
{
    switch(key){
      case "new":
       return factory.GetService<NewProcessor>();
      case "old":
       return factory.GetService<OldProcessor>();
    }
}

My Service class uses this factory and I need help to mock the same.

private readonly  Func<string,Iprocessor> _processor;

_processor is assigned using DI.

public void ProcessRecords(List<items> items){

    List<string> types = new List<string> () { "new", "old"};
    
    foreach(var type in types)
    {
      var processor = _processor(type); 
       if(processor != null)
       {
         _processor.Process(items);
       }
    }

}

How do I Mock the Process method calls?

Nkosi
  • 235,767
  • 35
  • 427
  • 472
as2007
  • 25
  • 3

1 Answers1

0

In order to make sure that everything is working fine you need to test each component separately. First you have to make sure that your OldProcessor and NewProcessor are working as expected.

After that you can focus on the ProcessRecords.
If I can assume that your service class receives the factory delegate inside its ctor:

class SUT
{
   private readonly Func<string,Iprocessor> _processor;
   public SUT(Func<string,Iprocessor> processor)
   {
      this._processor = processor;
   }

   public void ProcessRecords(List<items> items)
   {
      ...
   }
}

then in your case all you need to do it to create Iprocessor mock
and provide a delegate which will always resolve to this mock:

[Fact]
public void TestMethod1()
{
   //Arrange
   var processorMock = new Mock<Iprocessor>();
   Func<string, Iprocessor> factory = _ => processorMock.Object;
   var input = new List<items> { ... };

   //Act
   var sut = new SUT(factory);
   sut.ProcessRecords(input);

   //Assert
   processorMock.Verify(processor => processor.Process(input), Times.Exactly(2));
}

Then you can verify that the Process method has been called twice.


Or if you wish you can create two separate mocks:

[Fact]
public void TestMethod2()
{
   //Arrange
   var oldProcessorMock = new Mock<Iprocessor>();
   var newProcessorMock = new Mock<Iprocessor>();
   Func<string, Iprocessor> factory = 
      t => t == "new" 
        ? newProcessorMock.Object 
        : oldProcessorMock.Objet;

   var input = new List<items> { ... };

   //Act
   var sut = new SUT(factory);
   sut.ProcessRecords(input);

   //Assert
   oldProcessorMock.Verify(processor => processor.Process(input), Times.Once);
   newProcessorMock.Verify(processor => processor.Process(input), Times.Once);
}

UPDATE: Setup Process method

oldProcessorMock
   .Setup(processor => processor.Process(It.IsAny<List<items>>())
   .Verifiable();

newProcessorMock
   .Setup(processor => processor.Process(It.IsAny<List<items>>())
   .Verifiable();
Peter Csala
  • 17,736
  • 16
  • 35
  • 75