添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

XUnit is not my favourite testing tool; I already mentioned that in How to set up a test matrix in XUnit? . To be fair, none of the .NET test tooling is my favourite. They’re hard to customise and run more advanced configurations or performance exhausting tasks.

I heard good things about Fixie , but I’m not even sure if it’s actively maintained. And here’s the thing, testing framework is rarely the hill you’d like to die on. We should select it based on the team’s preferences, as they said: “When in Rome, do as the Romans do” . Although, in this case, it’s more walking like Egyptians .

Still, enough of this rant; let’s look at the customisation I brought you today.

Let’s say we’d like a global setup before running all tests in XUnit; for instance, set some settings or environment variables.

To do that, we need to follow the best object-oriented practices and create the following class:

namespace Your.Test.Project.Namespace;
public sealed class AssemblyFixture : XunitTestFramework
    public AssemblyFixture(IMessageSink messageSink)
        :base(messageSink)
        // Do your setup here

We also need to align with the best C# practices and sprinkle that with a bit of attributes magic, and add that before the class declaration:

[assembly: TestFramework("Your.Test.Project.Namespace.AssemblyFixture", "Your.Test.Project.AssemblyName")]

Then place this file in the test project.

**Could I show you a real-world example?” Yes, I can! Last week I explained how Marten code generation works. We call it through the command line. Marten uses Oakton for command line handling, so the last line in our application has to look like that.

return await app.RunOaktonCommands(args);

That’ll automatically start the web application, but unfortunately, not in tests. To do that, we need to instrument Oakton to autostart the host. We can do that by setting the following variable:

OaktonEnvironment.AutoStartHost = true;

You could use another project from the Critter Stack Alba that’d do it for you.

But I’m not using it, as I’m using my own Ogooreck, which is a thin wrapper on .NET testing tooling that helps you cut boilerplate in Behaviour-Driven Design style.

What to do, then? Of course, I could use the class defined above to set this variable. The whole code would look like

[assembly: TestFramework("Your.Test.Project.Namespace.AssemblyFixture", "Your.Test.Project.AssemblyName")]
namespace Your.Test.Project.Namespace;
public sealed class AssemblyFixture : XunitTestFramework
    public AssemblyFixture(IMessageSink messageSink)
        :base(messageSink)
        OaktonEnvironment.AutoStartHost = true;

This code will ensure the setting is applied once at the beginning of tests.

Be careful with it! This approach works well for the basic global setup that should apply to all tests. You should not do exhaustive initialisation like database setup. As you see, it allows only synchronous code, and we’re plugging into the XUnit bare bones. This code will be run during test discovery in the IDE etc. As it’s global code, remember it may impact your test isolation. This is fine for our case, as we want to change the global setting for all tests, but it might not be fine for your case.