You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何自定义FluentAssertion的错误提示信息以显示具体泛型类型名称?

Customizing FluentAssertions Error Messages to Show Pretty Generic Type Names

The Problem

I'm working with FluentAssertions to write integration tests for service registration, and I need to tweak the error messages to be more descriptive. Here's my current test code:

using (new AssertionScope()) {
    foreach (var parameterType in parameterTypes) {
        var fooType = typeof(IFoo<>);
        var genericType = fooType.MakeGenericType(parameterType);
        serviceProvider
            .GetService(genericType)
            .Should()
            .NotBeNull($"all Foo types should be registered");
    }
}

When a test fails, the default error message looks like this:

Expected serviceProvider.GetService(genericProviderType) not to be because all Foo types should be registered.

But I want it to display the human-friendly name of the generic type instead, using my existing type.GetPrettyName() method:

Expected IFoo not to be because all Foo types should be registered.

I've tried digging through FluentAssertions docs and source code, thinking I needed to modify the subject or identifier, but couldn't find the right approach. I also messed around with deferred context functions in the AssertionScope constructor, but ran into closure issues where the value got overwritten in the loop.

The Solution

The fix is straightforward: use FluentAssertions' WithIdentifier() method to explicitly set the subject text that appears in your error message. This replaces the auto-generated expression string with your custom pretty-printed type name.

Here's the updated code:

using (new AssertionScope()) {
    foreach (var parameterType in parameterTypes) {
        var fooType = typeof(IFoo<>);
        var genericType = fooType.MakeGenericType(parameterType);
        var prettyTypeName = genericType.GetPrettyName(); // Your existing formatting method

        serviceProvider
            .GetService(genericType)
            .Should()
            .WithIdentifier(prettyTypeName) // Override the default subject here
            .NotBeNull($"all Foo types should be registered");
    }
}

How This Works

  • WithIdentifier() lets you replace the default subject (the expression that FluentAssertions parses, like serviceProvider.GetService(genericType)) with any string you want. In this case, we use your GetPrettyName() output to show the clean generic type.
  • Unlike the deferred context approach you tried earlier, this sets the identifier per-assertion inside the loop, so each iteration uses the correct genericType value without closure-related bugs.

Bonus: More Readable Reason Syntax

If you prefer a cleaner chain, you can use the Because() method instead of passing the reason directly to NotBeNull()—this works seamlessly with WithIdentifier():

serviceProvider
    .GetService(genericType)
    .Should()
    .WithIdentifier(prettyTypeName)
    .NotBeNull()
    .Because("all Foo types should be registered");

内容的提问来源于stack exchange,提问作者ilitirit

火山引擎 最新活动