When running a unit test, it does not seem to continue through the repo/data return to continue processing and just fast forwards to the return. The gist of the code is:
namespace program
{
[FunctionName("Processor")]
public static async Task<Boolean> Processor([OrchestrationTrigger] IDurableOrchestrationContext context, ILogger log)
{
var eventDetails = context.GetInput<entitydataobject>();
IRepoData repo = null;
List<Guid> list;
try
{
repo = Repository();
list = repo.GetEntityList(Guid.Parse(entitydataobject.Guid), entitydataobject.Name);
}
catch(Exception ex)
{
log.LogError("Processor Error: " + ex.Message);
}
}
public static IRepoData Repository()
{
try
{
return new RepoData("Data Source=instance.local;Initial Catalog=database;integrated security=True;MultipleActiveResultSets=True;");
}
catch (Exception ex)
{
throw new Exception("Repository Error: " + ex.Message);
}
}
}
The gist of the Unit Test:
namespace Test
{
[TestClass]
[ExcludeFromCodeCoverage]
public class ProcessorTests
{
var mockContext = new Mock<IDurableOrchestrationContest>();
var inputData = JsonConvert.DeserializeObject<entitydataobject>(File.ReadAllText("file.json"));
var list = new List<Guid>();
var repository = new Mock<IRepository>();
var log = new Mock<ILogger>();
list.Add(new Guid());
list.Add(new Guid());
repository.Setup(repo => repo.GetEntityIdList(Guid.Parse("4D47AF6C-0000-0000-0000-000000000000", "string").Returns(list);
mockContext.Setup(x => x.GetInput<entitydataobject>()).Returns(entitydataobject);
var result = program.Processor(context.Object, log.Object);
Assert.IsTrue(result.Result);
}
}
My guess is that the repository setup is not passing through.
I tried to execute in VS 2022, and it progresses up to the point of repository/GetEntityList, but just skips over it/does not populate the list.
1
I tried your code and got the same error , the issues with the GetEntityList
method inside your unit test.
Update the Processor
Method:
Processor
to await asynchronous methods .Use async repository method to avoid blocking threads
public static async Task<Boolean> ProcessEntity([OrchestrationTrigger] IDurableOrchestrationContext context, ILogger log)
{
var eventDetails = context.GetInput<entitydataobject>();
IRepoData repo = null;
List<Guid> list;
try
{
repo = Repository();
list = await Task.Run(() => repo.GetEntityList(Guid.Parse(eventDetails.Guid), eventDetails.Name));
if (list != null && list.Count > 0)
{
return true;
}
return false;
}
catch (Exception ex)
{
log.LogError("Processor Error: " + ex.Message);
return false;
}
}
public static IRepoData Repository()
{
try
{
return new RepoData("Server=localhost\MSSQLSERVER01;Database=master;Trusted_Connection=True;");
}
catch (Exception ex)
{
throw new Exception("Repository Error: " + ex.Message);
}
}
}
Update the Unit test :
The IRepoData
interface and its implementation (RepoData
) have been refactored to be asynchronous, using Task<List<Guid>>
.The unit test uses await
to handle the asynchronous nature of Processor
. The repository mock now returns a Task
using .ReturnsAsync(list)
.
public class ProcessorTests
{
private readonly IDurableOrchestrationContext _context;
private readonly ILogger _logger;
private readonly IRepoData _repo;
private readonly entitydataobject _validEntityDataObject;
private readonly List<Guid> _entityList;
public ProcessorTests()
{
_context = Substitute.For<IDurableOrchestrationContext>();
_logger = Substitute.For<ILogger>();
_repo = Substitute.For<IRepoData>();
_validEntityDataObject = new entitydataobject
{
Guid = Guid.NewGuid().ToString(),
Name = "SampleName"
};
_entityList = new List<Guid> { Guid.NewGuid(), Guid.NewGuid() };
_context.GetInput<entitydataobject>().Returns(_validEntityDataObject);
}
[Fact]
public async Task ProcessEntity_ShouldReturnTrue_WhenDataIsProcessedSuccessfully()
{
_repo.GetEntityList(Arg.Any<Guid>(), Arg.Any<string>()).Returns(_entityList);
var result = await Processor.ProcessEntity(_context, _logger);