You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为插值字符串设置Mock?Logger接口单元测试疑问

Can You Mock the Interpolated String Template Instead of the Resolved Result?

Absolutely—but it depends on how your ILogger.Trace method is defined. Let me break this down clearly for you:

The Default Problem: Interpolated Strings as string

If your Trace method accepts a string parameter like this:

public interface ILogger
{
    void Trace(string message);
}

When you call logger.Trace($"User {userId} performed action {action}"), the C# compiler converts the interpolated string directly into a fully resolved string at compile time. By the time it reaches your mock, only the final concatenated text exists—there’s no way to recover the original template (like "User {userId} performed action {action}").

The Clean Solution: Use FormattableString

To capture the original interpolation template, modify your ILogger interface to accept a FormattableString instead of string:

public interface ILogger
{
    void Trace(FormattableString message);
}

FormattableString preserves both the raw template string and the individual values being interpolated. This lets your mock verify the exact template used, without tying your test to specific parameter values (great for keeping tests flexible).

Example with Moq

Here’s how you’d set up and verify the mock in your unit test:

// Arrange
var mockLogger = new Mock<ILogger>();
var service = new YourService(mockLogger.Object);
var userId = 123;
var action = "update";

// Act
service.DoSomeWork(userId, action);

// Assert: Verify the exact template was used
mockLogger.Verify(
    l => l.Trace(It.Is<FormattableString>(fs => 
        fs.Format == "User {0} performed action {1}"
    )), 
    Times.Once
);

You can even go further and validate the interpolated values if needed:

mockLogger.Verify(
    l => l.Trace(It.Is<FormattableString>(fs => 
        fs.Format == "User {0} performed action {1}" &&
        fs.GetArgument(0).Equals(userId) &&
        fs.GetArgument(1).Equals(action)
    )), 
    Times.Once
);

Workarounds If You Can’t Modify the Interface

If changing the ILogger interface isn’t an option, your next best bet is to use fuzzy matching on the resolved string (e.g., checking if it contains expected substrings):

mockLogger.Verify(
    l => l.Trace(It.Is<string>(s => 
        s.Contains($"User {userId}") && s.Contains("performed action")
    )), 
    Times.Once
);

This is less reliable than using FormattableString (since other unrelated strings could match), but it works as a fallback if you can’t adjust the interface.


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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 08:39:53