NSubstitute - 检查传递给方法的参数
NSubstitute - Check arguments passed to method
我们目前正在从 RhinoMocks 迁移到 NSubstitute。
我有一个接受类型 DatabaseParams
对象的方法。此 class 具有以下结构(简化):
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;
}
}
我有以下方法,我想检查传递给它的参数是否正确:
public interface IHelper
{
Task<object> ExecuteScalarProcedureAsync(DatabaseParams data);
}
如何测试 DatabaseParams
的实例是否以正确的值传递到该方法?
我可以在 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));
helperMock
正在模拟包含 ExecuteScalarProcedureAsync
方法的接口 IHelper
。
我自己想出了答案。
NSubstitute 只需要使用 .Received() 调用,然后在您为该方法指定参数时使用。您可以将参数匹配指定为谓词。
例如:
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"));
另一种方法是使用 Do
(参见 https://nsubstitute.github.io/help/actions-with-arguments/)。我更喜欢这个,因为它允许您针对参数的特定属性调用断言,这可以让您更好地反馈参数对象的哪些特定属性不正确。例如:
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());
晚会有点晚,但 运行 有同样的需要。
我在 java 中使用 mockito,他们有一个我喜欢的 Argument capture helper。
和@Castrohenge的回答基本一样
这是我的 NSubstitute 实现。
public interface IFoo
{
void DoSomthing(string stringArg);
}
参数捕获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;
}
}
以及使用测试用例
[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]);
}
我们目前正在从 RhinoMocks 迁移到 NSubstitute。
我有一个接受类型 DatabaseParams
对象的方法。此 class 具有以下结构(简化):
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;
}
}
我有以下方法,我想检查传递给它的参数是否正确:
public interface IHelper
{
Task<object> ExecuteScalarProcedureAsync(DatabaseParams data);
}
如何测试 DatabaseParams
的实例是否以正确的值传递到该方法?
我可以在 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));
helperMock
正在模拟包含 ExecuteScalarProcedureAsync
方法的接口 IHelper
。
我自己想出了答案。
NSubstitute 只需要使用 .Received() 调用,然后在您为该方法指定参数时使用。您可以将参数匹配指定为谓词。
例如:
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"));
另一种方法是使用 Do
(参见 https://nsubstitute.github.io/help/actions-with-arguments/)。我更喜欢这个,因为它允许您针对参数的特定属性调用断言,这可以让您更好地反馈参数对象的哪些特定属性不正确。例如:
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());
晚会有点晚,但 运行 有同样的需要。 我在 java 中使用 mockito,他们有一个我喜欢的 Argument capture helper。 和@Castrohenge的回答基本一样
这是我的 NSubstitute 实现。
public interface IFoo
{
void DoSomthing(string stringArg);
}
参数捕获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;
}
}
以及使用测试用例
[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]);
}