I try to write a bunit test for the component EditProposal in a Blazor server side project. I have strange behavior that my test continues without error in 1 out of 10 times and the other times I get one of the following errors:
System.InvalidOperationException : BeginExecuteReader requires an open and available Connection. The connection's current state is closed.
at Microsoft.Data.SqlClient.SqlCommand.<>c.<ExecuteDbDataReaderAsync>b__188_0(Task`1 result)
and sometimes the error
System.InvalidOperationException : The connection does not support MultipleActiveResultSets.
at Microsoft.Data.SqlClient.SqlCommand.<>c.<ExecuteDbDataReaderAsync>b__188_0(Task`1 result)
This is my basic test setup:
[Test]
public async Task EditProposal_ItSavesAnEditedProposal()
{
using var ctx = new TestContext();
ctx.Services.AddSingleton(_proposalService);
ctx.Services.AddSingleton(_skillableService);
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
var cut = ctx.RenderComponent<EditProposal>(parameters =>
parameters.Add(p => p.Id, "1"));
cut.WaitForState(() => cut.FindAll("tr").Count > 0, TimeSpan.FromSeconds(15));
cut.Find("input").Change("TestTitle");
cut.Find("textarea").Change("A new proposal description");
cut.Find("select").Change("Beratung");
cut.Find("form").Submit();
It fails for the following method:
public async Task<List<Skill>> GetAllSkillsForSkillableType(string skillableType, int skillableTypeId)
{
var sql =
$"select ParentId, s.Id, Type, Name from skill s inner join Skillable sa on sa.SkillId = s.Id inner join {skillableType} p on p.Id = sa.{skillableType}Id Where {skillableType}Id = {skillableTypeId};";
var skills = (await DbConnection.QueryAsync<Skill>(sql)).ToList();
skills = await SetAllParents(skills);
return skills;
}
exactly this line: var skills = (await DbConnection.QueryAsync<Skill>(sql)).ToList();
I call this method within the ProposalService which is used to load the specific proposal into my edit proposal from the database:
public async Task<Proposal> GetProposalAsync(int id)
{
var parameters = new {Id = id};
var sql = "SELECT * FROM proposal WHERE id = @Id";
var result = await DbConnection.QuerySingleOrDefaultAsync<Proposal>(sql, parameters);
if (result == null) result = new Proposal();
result.Skills = await SkillableServiceAsync.GetAllSkillsForSkillableType("Proposal", result.Id);
if (result.Skills.Count == 0 && result.Equals(new Proposal())) return null;
return result;
}
It seems to be related to the dapper methods.
Something which is really strange about this that it happens only within bunit tests and never on the browser or in the integration tests for the service methods. I think I might have to mock the service altogether but it seems to be more a bug or is there anything wrong with my code?
How can I fix this without having to mock the service?
update
I was able to find a possible answer here.
Giving the second method another connection seems to make it fail in less cases. As a note: I abandoned opening connection by myself from the services with using:
services.AddTransient<IDbConnection>(sp => new SqlConnection(DatabaseUtils.ConnectionString)); in startup.cs