当集合的固定装置抛出异常时,如何使集合失败?

发布于 2025-01-12 13:26:41 字数 2265 浏览 1 评论 0原文

我目前正在为成熟的 ASP.NET 应用程序编写一套集成测试。 作为应用程序支持服务的一部分,它使用 Azure blob 存储容器,我需要在运行测试之前确保该容器可访问且存在。我想添加实际上等于检查为应用程序配置的 Azure blob 容器(无论是在本地模拟器上还是在 CI 中运行时的 Azure 本身)是否已启动并准备好处理测试套件发出的请求。如果后端无法访问,大量测试将直接失败,并且由于 Azure 库会等待多次超时,因此需要几分钟时间才会失败。

当在集合固定装置中抛出或断言时,它似乎实际上并没有阻止集合中的任何测试运行,固定装置异常也不会出现在结果日志中。

如果在实例化过程中任何相关的固定装置抛出异常,是否有办法阻止测试运行?


我当前的代码如下:

夹具

using Azure.Storage.Blobs;
using Newtonsoft.Json.Linq;
using System.IO;
using Xunit;

namespace product.test.integration
{
    /// <summary>
    /// This fixture ensures the configured azure blob container used by the FileStorage system is accessible.
    /// A concern mostly in local environments where the Azurite emulator may not be running, but also can alert to a misconfigured testing environment.
    /// </summary>
    public class FileStorageFixture
    {
        public FileStorageFixture()
        {
            //get the configuration
            string appdataLocation = Path.Combine(Directory.GetCurrentDirectory(), "testappsettings.json");
            string appdataContent = File.ReadAllText(appdataLocation);
            var json = JObject.Parse(appdataContent);
            string connectionString = json["Settings"]["FileStorage"]["AzureStorageKey"].Value<string>();
            string containerName = json["Settings"]["FileStorage"]["ContainerName"].Value<string>();
            //check if the container exists
            var container = new BlobContainerClient(connectionString, containerName);
            try
            {
                Assert.True(container.Exists()); //this line will throw if a timeout occurs
            } catch
            {
                throw new System.Exception("Configured FileStorage backend is not accessible!");
            }
        }
    }
}

所有测试扩展的基测试类(IntegrationTest)以及包含它们的集合:

//...
    [CollectionDefinition("Integration Tests", DisableParallelization = true)]
    public class IntegrationTestCollection :
        //...
        ICollectionFixture<FileStorageFixture> { }

    [Collection("Integration Tests")]
    public abstract class IntegrationTest : IClassFixture<WebApplicationFactory<product.api.Startup>>
    {
//...

I'm currently writing a suite of integration tests for a mature ASP.NET application.
As part of the application's supporting services, it uses an Azure blob storage container which I need to make sure is accessible and existing prior to running the tests. I want to add what effectively amounts to a check that the configured Azure blob container for the application (be it on the local emulator or Azure itself when running in CI) is up and ready to handle the requests made by the test suite. A large amount of the tests will straight up fail if the backend is inaccessible and they take several minutes to fail as the Azure library waits through several timeouts.

When throwing or asserting in a collection fixture, it doesn't seem to actually prevent any test in the collection from running nor does the fixture exception appear in the resulting logs.

Is there a way to prevent tests from running if any of their associated fixtures throw during instantiation?


My current code is as follows:

The fixture

using Azure.Storage.Blobs;
using Newtonsoft.Json.Linq;
using System.IO;
using Xunit;

namespace product.test.integration
{
    /// <summary>
    /// This fixture ensures the configured azure blob container used by the FileStorage system is accessible.
    /// A concern mostly in local environments where the Azurite emulator may not be running, but also can alert to a misconfigured testing environment.
    /// </summary>
    public class FileStorageFixture
    {
        public FileStorageFixture()
        {
            //get the configuration
            string appdataLocation = Path.Combine(Directory.GetCurrentDirectory(), "testappsettings.json");
            string appdataContent = File.ReadAllText(appdataLocation);
            var json = JObject.Parse(appdataContent);
            string connectionString = json["Settings"]["FileStorage"]["AzureStorageKey"].Value<string>();
            string containerName = json["Settings"]["FileStorage"]["ContainerName"].Value<string>();
            //check if the container exists
            var container = new BlobContainerClient(connectionString, containerName);
            try
            {
                Assert.True(container.Exists()); //this line will throw if a timeout occurs
            } catch
            {
                throw new System.Exception("Configured FileStorage backend is not accessible!");
            }
        }
    }
}

The base test class (IntegrationTest) which all tests extend, and the collection that contains them:

//...
    [CollectionDefinition("Integration Tests", DisableParallelization = true)]
    public class IntegrationTestCollection :
        //...
        ICollectionFixture<FileStorageFixture> { }

    [Collection("Integration Tests")]
    public abstract class IntegrationTest : IClassFixture<WebApplicationFactory<product.api.Startup>>
    {
//...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

海的爱人是光 2025-01-19 13:26:41

实现您想要的目的的一种方法是让夹具在初始化不成功时设置一个标志,并在基测试类的构造函数中查询该标志。

FileStorageFixture 中添加标志作为属性

    public bool initOK { get; private set; } = false;

,并根据初始化是否成功设置该属性

     try
     {
        Assert.True(container.Exists()); //this line will throw if a timeout occurs
        initOK = true;
     } 
     catch
     {
        initOK = false;
     }

如果将其余代码包含在 FileStorageFixture 中,会更加可靠try 中的构造函数,因为任何地方的异常也会导致测试失败。

我假设对固定装置的引用作为参数提供给 IntegrationTest 的构造函数,因此如果固定装置未正确初始化,您应该在那里抛出异常:

    public IntegrationTest(FileStorageFixture fixture) 
    {
        Assert.True(fixture.initOK, "Configured FileStorage backend is not accessible!");

        // ... and do the rest of the constructor stuff
    }

没有 IntegrationTest 对象,它的任何测试都不会运行。

One way to accomplish what you desire is to have the fixture set a flag if its initialization was not successful and query the flag in the constructor of your base test class.

In FileStorageFixture add the flag as a property

    public bool initOK { get; private set; } = false;

and set the property depending on whether the initialization was successful

     try
     {
        Assert.True(container.Exists()); //this line will throw if a timeout occurs
        initOK = true;
     } 
     catch
     {
        initOK = false;
     }

It would be even more reliable if you included the rest of the code in the FileStorageFixture constructor inside the try, since an exception anywhere there would also bring your tests down.

I assume the reference to the fixture is being provided as a parameter to the constructor of IntegrationTest, so you should throw an exception there if the fixture wasn't initialized properly:

    public IntegrationTest(FileStorageFixture fixture) 
    {
        Assert.True(fixture.initOK, "Configured FileStorage backend is not accessible!");

        // ... and do the rest of the constructor stuff
    }

Without the IntegrationTest object, none of its tests will run.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文