We are adding UI unit tests for our Blazor project and diving into evaluating your JustMock and your testing framework. i am trying to create a test that invokes AddReleaseAsync method, but nothing that I have tried avoids a compile error, that I am showing below. We have a form that has a Blazor grid, initially populated with the data returned from GetReleasesAsync method, and then we add a new row using AddReleaseAsync expecting to see an additional data row. A simple test that uses only GetReleasesAsync method and checks that 2 data rows are returned works fine. But I can't compile the below test for adding a row. How do I mock an async method returning an anonymous type? We are using a pattern returning <string message, IEnumerable<T> data> quite extensively in our services to pass info/error Message and Data to the UI. Is it possible to mock the AddReleaseAsync and if so, how ?
P.S. I understand that test is not quite 'complete', but I can't get past the compile error to properly write the test
Given this interface
public interface IApiLogic
{
Task<IEnumerable<Release>> GetReleasesAsync(); // gets all data
Task<(string Message, IEnumerable<Release>? Releases)> AddReleaseAsync(Release release);
}
And the below test method,
[TestMethod]
public void CanAddnewRelease()
{
// Arrange
var apiMock = Mock.Create<IApiLogic>();
Mock.Arrange(() => apiMock.GetReleasesAsync()).ReturnsAsync(DummyReleases(2));
var response = new { Message = "ok", Releases = DummyReleases(3)};
// 1. Tried this (and many other things, but always get a similar error)
Mock.Arrange(() => apiMock.AddReleaseAsync(Arg.IsAny<Release>())).ReturnsAsync(response);
/* I get compile error for the above line
Error CS1503 Argument 2: cannot convert from '<anonymous type: string Message, System.Collections.Generic.IEnumerable<SDCSSPxte.Shared.Entities.Release> Releases>' to 'System.Func<(string Message, System.Collections.Generic.IEnumerable<SDCSSPxte.Shared.Entities.Release> Releases)>'
*/
// 2. Tried this
Mock.Arrange(() => apiMock.AddReleaseAsync(Arg.IsAny<Release>())).Returns(Task.FromResult<(string Message, IEnumerable<Release>? Releases)>(response));
/* I get compile error on the above line
Error CS1503 Argument 1: cannot convert from '<anonymous type: string Message, System.Collections.Generic.IEnumerable<SDCSSPxte.Shared.Entities.Release> Releases>' to '(string Message, System.Collections.Generic.IEnumerable<SDCSSPxte.Shared.Entities.Release>? Releases)'
*/
var ctx = new Bunit.TestContext();
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
ctx.Services.AddSingleton<IApiLogic>(apiMock);
ctx.Services.AddTelerikBlazor();
var rootComponentMock = Mock.Create<TelerikRootComponent>();
// Act
var cut = ctx.RenderComponent<SDCSSPxte.Client.Pages.Admin.Release>(parameters => parameters.AddCascadingValue<TelerikRootComponent>(rootComponentMock));
var addButton = cut.FindAll(".k-button-text")[0];
addButton.Click();
// Assert
var dataRows = cut.FindAll("tbody tr");
dataRows.Count.Should().Be(3);
dataRows[0].ChildNodes.FirstOrDefault(n => n.TextContent.Trim() == "ReleaseComment for r1").Should().NotBeNull();
dataRows[1].ChildNodes.FirstOrDefault(n => n.TextContent.Trim() == "ReleaseComment for r2").Should().NotBeNull();
dataRows[2].ChildNodes.FirstOrDefault(n => n.TextContent.Trim() == "ReleaseComment for r3").Should().NotBeNull();
}
// You should be able to infer what the Release class is, it is in a separate project, SDCSSPxte.Shared.Entities. namespace)
private List<Release> DummyReleases (int count){
List<Release> releases = new();
for (int c=0; c < count; c++)
{
releases.Add(new Release()
{
ReleaseKey = 1,
ReleaseDate = DateTime.Now.Date,
ReleasePackageName = $"ReleasePackageName{c+1}",
Comment = $"ReleaseComment for r{c+1}"
});
}
return releases;
}