简体   繁体   English

NSubstitute-检查传递给方法的参数

[英]NSubstitute - Check arguments passed to method

We are currently in the process of moving from RhinoMocks to NSubstitute. 我们目前正在从RhinoMocks迁移到NSubstitute。

I have a method that takes an object of type DatabaseParams . 我有一个采用类型为DatabaseParams的对象的方法。 This class has the following structure (simplified): 此类具有以下结构(简化):

public class DatabaseParams
  {
    public string StoredProcName { get; private set; }
    public SqlParameter[] Parameters { get; private set; }

    public DatabaseParams(string storeProcName, SqlParameter[] spParams)
    {
      StoredProcName = storeProcName;
      Parameters = spParams;
    }
  }

I have the following method I want to check the arguments being passed to it are correct: 我有以下方法,我想检查传递给它的参数是否正确:

public interface IHelper
{
Task<object> ExecuteScalarProcedureAsync(DatabaseParams data);
}

How do I test that an instance of DatabaseParams was passed into that method with the correct values? 如何测试以正确的值将DatabaseParams实例传递给该方法?

I could do this in RhinoMocks with something like this: 我可以在RhinoMocks中执行以下操作:

helperMock.Expect(m => m.ExecuteScalarProcedureAsync(Arg<DatabaseHelperParameters>.Matches(
        p =>   p.StoredProcName == "up_Do_Something"
            && p.Parameters[0].ParameterName == "Param1"
            && p.Parameters[0].Value.ToString() == "Param1Value"
            && p.Parameters[1].ParameterName == "Param2"
            && p.Parameters[1].Value.ToString() == "Param2Value"
        ))).Return(Task.FromResult<DataSet>(null));

The helperMock is mocking the interface IHelper that contains the ExecuteScalarProcedureAsync method. helperMock正在IHelper包含ExecuteScalarProcedureAsync方法的接口IHelper

I've figured out the answer myself. 我自己已经找到答案了。

NSubstitute just needs to use the .Received() call and then when you specify your argument to the method. NSubstitute仅需要使用.Received()调用,然后在为该方法指定参数时使用。 You can specify the argument matching as a predicate. 您可以将匹配的参数指定为谓词。

For example: 例如:

  helperMock.Received().ExecuteScalarProcedureAsync(Arg.Is<DatabaseParams>(
   p =>   p.StoredProcName == "up_Do_Something"
        && p.Parameters[0].ParameterName == "Param1"
        && p.Parameters[0].Value.ToString() == "Param1Value"
        && p.Parameters[1].ParameterName == "Param2"
        && p.Parameters[1].Value.ToString() == "Param2Value"));

An alternative is to use Do (see https://nsubstitute.github.io/help/actions-with-arguments/ ). 一种替代方法是使用Do (请参阅https://nsubstitute.github.io/help/actions-with-arguments/ )。 I prefer this as it lets you call assertions against specific properties of the arguments, which gives you better feedback on which specific properties of the argument object are incorrect. 我更喜欢这样做,因为它使您可以针对参数的特定属性调用断言,从而为您提供有关参数对象的特定属性不正确的更好的反馈。 For example: 例如:

StoredProc sp = null; // Guessing the type here

helperMock.Received().ExecuteScalarProcedureAsync(Arg.Do<DatabaseParams>(p => sp = p));

// NUnit assertions, but replace with whatever you want.
Assert.AreEqual("up_Do_Something", sp.StoredProcName);
Assert.AreEqual("Param1", p.Parameters[0].ParameterName);
Assert.AreEqual("Param1Value", p.Parameters[0].Value.ToString());
Assert.AreEqual("Param2", p.Parameters[1].ParameterName);
Assert.AreEqual("Param2Value", p.Parameters[1].Value.ToString());

A bit late for the party, but ran into the same need. 晚会晚了一点,但遇到了同样的需要。 I am working with mockito in java, and they have an Argument capture helper that I like. 我正在使用Java中的Mockito,并且他们有一个我喜欢的Argument捕获助手。 It is basically the same as @Castrohenge answer 它与@Castrohenge答案基本相同

So here is my NSubstitute implementation. 这是我的NSubstitute实现。

public interface IFoo
{
    void DoSomthing(string stringArg);
}

Argument capture class 参数捕获类

public class ArgCapture<T>
{
    private List<T> m_arguments = new List<T>();

    public T capture()
    {
        T res = Arg.Is<T>(obj => add(obj)); // or use Arg.Compat.Is<T>(obj => add(obj)); for C#6 and lower
        return res;
    }

    public int Count
    {
        get { return m_arguments.Count; }
    }

    public T this[int index]
    {
        get { return m_arguments[index]; }
    }

    public List<T> Values {
        get { return new List<T>(m_arguments);}
    }

    private bool add(T obj)
    {
        m_arguments.Add(obj);
        return true;
    }
}

And the usage test case 和用法测试用例

    [Test]
    public void ArgCaptureTest()
    {
        IFoo foo1 = Substitute.For<IFoo>();
        ArgCapture<string> stringArgCapture = new ArgCapture<string>();
        foo1.DoSomthing("firstCall");
        foo1.DoSomthing("secondCall");
        foo1.Received(2).DoSomthing(stringArgCapture.capture());
        Assert.AreEqual(2,stringArgCapture.Count);
        Assert.AreEqual("firstCall",stringArgCapture[0]);
        Assert.AreEqual("secondCall", stringArgCapture[1]);
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM