我有以下界面

public interface IRibbonCommandsProvider
{
    IEnumerable<IRibbonCommand> GetRibbonCommands();
}
public interface IRibbonCommand
{
    string Group { get; }
    string Tab { get; }
    string Name { get; }
    string Image { get; }
    void Execute();
}


和下面的替换代码:

public class TabsViewModelTests
{
    [Fact]
    public void Initialize_BuildsCorrectRibbonTree()
    {
        var commands = Substitute.For<IRibbonCommandsProvider>();
        commands.GetRibbonCommands().Returns(
            new[]
            {
                new RibbonCommand { Tab = "Tab1", Group = "Group1", Name = "Name1" },
                new RibbonCommand { Tab = "Tab1", Group = "Group1", Name = "Name2" },
                new RibbonCommand { Tab = "Tab2", Group = "Group1", Name = "Name3" },
                new RibbonCommand { Tab = "Tab2", Group = "Group2", Name = "Name3" }
            });
           ...
    }

    private class RibbonCommand : IRibbonCommand
    {
        public string Group { get; set; }
        public string Tab { get; set; }
        public string Name { get; set; }
        public string Image { get; set; }
        public void Execute() {}
    }
}


使用NSubstitute,是否有一种聪明的方法来摆脱存根RibbonCommand类(那只是一个伪造的IRibbonCommand实现-这是NSubstitute的工作),并且仍然具有伪造的丝带命令列表,该列表像上面一样容易阅读? 。

我不能使用NSubsitute的.Returns()流利方法提出一种可读的方法,而不会以更多(且不可读)的代码结尾。

更新:
很酷的NSubstitute扩展方法看起来像这样。我只是不知道是否以及如何构建:

public static ConfiguredCall ReturnsMany<T>(
    this IEnumerable<T> value,
    Action<T> configureThis,
    params Action<T>[] configureThese)
{
    ...
}


它的用法如下:

commands.GetRibbonCommands().ReturnsMany(
    subst =>
    {
        subst.Tab.Returns("Tab1");
        subst.Group.Returns("Group1");
        subst.Name.Returns("Name1");
    },
    subst =>
    {
        subst.Tab.Returns("Tab1");
        subst.Group.Returns("Group1");
        subst.Name.Returns("Name2");
    },
    subst =>
    {
        subst.Tab.Returns("Tab2");
        subst.Group.Returns("Group1");
        subst.Name.Returns("Name3");
    },
    subst =>
    {
        subst.Tab.Returns("Tab2");
        subst.Group.Returns("Group1");
        subst.Name.Returns("Name3");
    });

最佳答案

我认为您所拥有的非常好-简洁明了。

如果您真的想摆脱该类,可以使用IRibbonCommand的替代创建方法:

    private IRibbonCommand Create(string tab, string group, string name)
    {
        var cmd = Substitute.For<IRibbonCommand>();
        cmd.Tab.Returns(tab);
        cmd.Group.Returns(group);
        cmd.Name.Returns(name);
        return cmd;
    }

    [Fact]
    public void Initialize_BuildsCorrectRibbonTree()
    {
        var ribbonCommands = new[] {
            Create("tab1", "group1", "name1"),
            Create("tab1", "group1", "name2"),
            Create("tab2", "group1", "name3"),
            Create("tab2", "group1", "name4")
        };
        var commands = Substitute.For<IRibbonCommandsProvider>();
        commands.GetRibbonCommands().Returns(ribbonCommands);
        // ...
    }


这并不会给您带来多少好处,尽管这确实意味着您的测试代码将受到更多保护,以免更改IRibbonCommand接口(例如,无需更改测试代码即可获得其他属性),并且意味着您可以检查收到的呼叫和存根。其他要求单独处理的项目。



另外:如果您想更匹配原始代码,可以使用参数名称:

    Create(tab: "tab1", group: "group1", name: "name1"),

09-06 01:36