1

我尝试为EditProposalBlazor 服务器端项目中的组件编写 bunit 测试。我有奇怪的行为,我的测试在 10 次中有 1 次继续没有错误,而其他时候我得到以下错误之一:

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)

有时错误

System.InvalidOperationException : The connection does not support MultipleActiveResultSets.
   at Microsoft.Data.SqlClient.SqlCommand.<>c.<ExecuteDbDataReaderAsync>b__188_0(Task`1 result)

这是我的基本测试设置:

[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();

以下方法失败:

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;
}

正是这一行:var skills = (await DbConnection.QueryAsync<Skill>(sql)).ToList();

我在其中调用此方法ProposalService,用于将特定提案从数据库加载到我的编辑提案中:

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;
}

它似乎与dapper方法有关。

对此真的很奇怪,它只发生在 bunit 测试中,而不会发生在浏览器或服务方法的集成测试中。我想我可能不得不完全模拟该服务,但它似乎更像是一个错误,或者我的代码有什么问题吗?

如何在不必模拟服务的情况下解决此问题?

更新

我能够在这里找到一个可能的答案。

给第二种方法另一个连接似乎使它在较少的情况下失败。注意:我使用以下服务放弃了自己打开连接:

services.AddTransient<IDbConnection>(sp => new SqlConnection(DatabaseUtils.ConnectionString));startup.cs

4

1 回答 1

0

所以给失败的线路一个自己的连接解决了这个问题:

using IDbConnection dbConnection = new SqlConnection(DatabaseUtils.ConnectionString);
var results = (await dbConnection.QueryAsync<Skill>(sql, new { ids = Ids })).ToList();

我认为它只对 bunit 失败,因为它的执行速度比浏览器快一点。问题是我的方法被调用了两次,但尝试使用相同的连接。因此,当一个关闭它时,另一个仍然需要访问。

于 2021-07-09T18:24:43.523 回答