Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/299.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 不使用魔术字符串将参数传递给假调皮的模拟?_C#_Unit Testing_Moq_Fakeiteasy - Fatal编程技术网

C# 不使用魔术字符串将参数传递给假调皮的模拟?

C# 不使用魔术字符串将参数传递给假调皮的模拟?,c#,unit-testing,moq,fakeiteasy,C#,Unit Testing,Moq,Fakeiteasy,在过去的几年里,我一直在用它来满足我的嘲弄需求,但在看过之后,我想尝试一下 我经常想测试是否使用正确的参数调用了一个方法,但我发现没有令人满意的方法使用FakeiTasy来实现这一点 我有以下代码要测试: public class WizardStateEngine : IWizardStateEngine { private readonly IWorkflowInvoker _workflowInvoker; private List<CustomBookmar

在过去的几年里,我一直在用它来满足我的嘲弄需求,但在看过之后,我想尝试一下

我经常想测试是否使用正确的参数调用了一个方法,但我发现没有令人满意的方法使用FakeiTasy来实现这一点

我有以下代码要测试:

    public class WizardStateEngine : IWizardStateEngine
{
    private readonly IWorkflowInvoker _workflowInvoker;
    private List<CustomBookmark> _history;

    public WizardStateEngine(IWorkflowInvoker workflowInvoker)
    {
        _workflowInvoker = workflowInvoker;
    }

    public void Initialize(List<CustomBookmark> history)
    {
        _history = history;
    }

    public WizardStateContext Execute(Command command, WizardStateContext stateContext, CustomBookmark step)
    {
        Activity workflow = new MyActivity();
        var input = new Dictionary<string, object>();
        input["Action"] = command;
        input["Context"] = stateContext;
        input["BookmarkHistory"] = _history;

        var output = _workflowInvoker.Invoke(workflow, input);

        _history = output["BookmarkHistory"] as List<CustomBookmark>;

        return output["Context"] as WizardStateContext;
    }

    public List<CustomBookmark> GetBookmarkHistory()
    {
        return _history;
    }
}
公共类WizardStateEngine:IWizardStateEngine
{
私有只读IWorkflowInvoker\u workflowInvoker;
私人名单(历史),;
公共WizardStateEngine(IWorkflowInvoker workflowInvoker)
{
_workflowInvoker=workflowInvoker;
}
公共无效初始化(列表历史记录)
{
_历史=历史;
}
公共WizardStateContext执行(命令、WizardStateContext stateContext、CustomBookmark步骤)
{
活动工作流=新建MyActivity();
var输入=新字典();
输入[“操作”]=命令;
输入[“上下文”]=状态上下文;
输入[“书签历史记录”]=\u历史记录;
var output=_workflowInvoker.Invoke(工作流,输入);
_历史记录=输出[“书签历史记录”]作为列表;
将输出[“上下文”]作为WizardStateContext返回;
}
公共列表GetBookmarkHistory()
{
回归历史;
}
}
我想编写一些测试来验证对_workflowInvoker.Invoke()的输入。 我的TestInitialize方法设置所需的资源,并将输入字典保存到_workflowInvoker.Invoke()作为本地字段_wfInput

    [TestInitialize]
    public void TestInitialize()
    {
        _wizardStateContext = new WizardStateContext();
        _workflowInvoker = A.Fake<IWorkflowInvoker>();
        _wizardStateEngine = new WizardStateEngine(_workflowInvoker);

        _outputContext = new WizardStateContext();
        _outputHistory = new List<CustomBookmark>();
        _wfOutput = new Dictionary<string, object>
                        {{"Context", _outputContext}, {"BookmarkHistory", _outputHistory}};

        _history = new List<CustomBookmark>();

        A.CallTo(() =>
                 _workflowInvoker.Invoke(A<Activity>.Ignored, A<Dictionary<string, object>>.Ignored))
            .Invokes(x => _wfInput = x.Arguments.Get<Dictionary<string, object>>("input"))
            .Returns(_wfOutput);

        _wizardStateEngine.Initialize(_history);
    }
[测试初始化]
public void TestInitialize()
{
_wizardStateContext=新wizardStateContext();
_workflowInvoker=A.false();
_wizardStateEngine=新wizardStateEngine(_workflowInvoker);
_outputContext=新建WizardStateContext();
_OutputhHistory=新列表();
_wfOutput=新字典
{{“上下文”、“输出上下文”}、{“书签历史”、“输出历史”};
_历史=新列表();
A.CallTo(()=>
_workflowInvoker.Invoke(A.Ignored,A.Ignored))
.Invokes(x=>\u wfInput=x.Arguments.Get(“输入”))
.返回值(_wfOutput);
_wizardStateEngine.Initialize(_历史记录);
}
安装后,我有多个测试,如下所示:

    [TestMethod]
    public void Should_invoke_with_correct_command()
    {
        _wizardStateEngine.Execute(Command.Start, null, null);

        ((Command) _wfInput["Action"]).ShouldEqual(Command.Start);
    }

    [TestMethod]
    public void Should_invoke_with_correct_context()
    {
        _wizardStateEngine.Execute(Command.Start, _wizardStateContext, null);

        ((WizardStateContext) _wfInput["Context"]).ShouldEqual(_wizardStateContext);
    }

    [TestMethod]
    public void Should_invoke_with_correct_history()
    {
        _wizardStateEngine.Execute(Command.Start, _wizardStateContext, null);

        ((List<CustomBookmark>) _wfInput["BookmarkHistory"]).ShouldEqual(_history);
    }
    [TestMethod]
    public void Should_invoke_with_correct_context()
    {
        _wizardStateEngine.Execute(Command.Start, _wizardStateContext, null);

        A.CallTo(() =>
                 _workflowInvoker.Invoke(A<Activity>._,
                                         A<Dictionary<string, object>>.That.Matches(
                                             x => (WizardStateContext) x["Context"] == _wizardStateContext)))
            .MustHaveHappened();
    }
[TestMethod]
public void应使用正确的命令()调用
{
_wizardStateEngine.Execute(Command.Start,null,null);
((命令)输入[“操作]).ShouldEqual(命令.Start);
}
[测试方法]
public void应使用正确的上下文()调用
{
_Execute(Command.Start,_wizardStateContext,null);
((WizardStateContext)\u wfInput[“Context”])。应该相等(\u WizardStateContext);
}
[测试方法]
public void应使用正确的历史调用
{
_Execute(Command.Start,_wizardStateContext,null);
((列表)输入[“书签历史记录])。应该相等(_历史记录);
}
我不喜欢TestInitialize中用于获取传递的参数(或幻数)的神奇字符串“input”。我可以在没有本地字段的情况下编写测试,如下所示:

    [TestMethod]
    public void Should_invoke_with_correct_command()
    {
        _wizardStateEngine.Execute(Command.Start, null, null);

        ((Command) _wfInput["Action"]).ShouldEqual(Command.Start);
    }

    [TestMethod]
    public void Should_invoke_with_correct_context()
    {
        _wizardStateEngine.Execute(Command.Start, _wizardStateContext, null);

        ((WizardStateContext) _wfInput["Context"]).ShouldEqual(_wizardStateContext);
    }

    [TestMethod]
    public void Should_invoke_with_correct_history()
    {
        _wizardStateEngine.Execute(Command.Start, _wizardStateContext, null);

        ((List<CustomBookmark>) _wfInput["BookmarkHistory"]).ShouldEqual(_history);
    }
    [TestMethod]
    public void Should_invoke_with_correct_context()
    {
        _wizardStateEngine.Execute(Command.Start, _wizardStateContext, null);

        A.CallTo(() =>
                 _workflowInvoker.Invoke(A<Activity>._,
                                         A<Dictionary<string, object>>.That.Matches(
                                             x => (WizardStateContext) x["Context"] == _wizardStateContext)))
            .MustHaveHappened();
    }
[TestMethod]
public void应使用正确的上下文()调用
{
_Execute(Command.Start,_wizardStateContext,null);
A.CallTo(()=>
_workflowInvoker.Invoke(A.),
A.那是火柴(
x=>(WizardStateContext)x[“上下文”]==\u WizardStateContext)))
.一定发生过();
}
但我发现使用本地字段的测试更具可读性

有没有办法设置将输入保存为测试类中的字段,而不使用幻数或字符串

我希望问题中更新的示例说明我为什么要使用本地字段。如果我能找到一种可读性好的方法,我非常愿意在没有本地字段的情况下编写测试

A.CallTo(()=>service.DoSomething(A.That.Matches(x=>x==100)))
A.CallTo(() => service.DoSomething(A<int>.That.Matches(x => x == 100)))
 .MustHaveHappened();
.一定发生过();
我同意达林所说的一切,做你正在做的事情似乎是一种不好的做法。在这个小例子中,你说它看起来“愚蠢”,你能提供一个它看起来聪明的例子吗

无论如何,以下试验将具有与Moq试验完全相同的行为:

[Test]
public void Should_do_something_with_correct_input()
{
    int inputNumber = 0;

    var service = A.Fake<IService>();
    A.CallTo(() => service.DoSomething(A<int>._))
        .Invokes((int x) => inputNumber = x);

    var system = new System(service);
    system.InvokeService();

    inputNumber.ShouldEqual(100);
}
[测试]
public void应该用正确的输入做某事
{
int inputNumber=0;
var service=A.Fake();
A.CallTo(()=>service.DoSomething(A.)
.调用((int x)=>inputNumber=x);
var系统=新系统(服务);
system.InvokeService();
输入编号。应等于(100);
}

谢谢你的回答,但这不是我想要的。我想将输入保存为测试类中的一个字段。这样,我可以在设置中设置一次,然后在多个测试中使用局部变量。对于复杂的对象,表达式可能很难读取。我会更新我的问题。@Olsenius,你为什么要这么做?您可以在lambda中执行必要的断言。您不再需要调用
inputNumber.ShouldEqual(100)。我更新了我的问题。我想将输入保存为多个测试的字段,并且只进行一次设置。@Olsenius,您试图做的是错误的实践IMHO。单元测试应该彼此独立,并且您不应该让一个测试初始化应该由另一个测试使用的数据。另一方面,您可以编写一个函数,该函数将在每个测试的
a.That.Matches
约束中调用,以验证数据。实际上,在这种情况下,没有理由使用参数约束“a.That.Matches(x=>x==100)”。只需使用“A.CallTo(()=>service.DoSomething(100)).musthaveOccessed();”我用我试图测试的实际类更新了我的问题。我也不想使用幻数,Moq的实现是完全等效的,就像mag一样