[英]Using Nsubstitute for mocking but getting an error
I am new to unit testing, so pardon me if I am unable to explain this question properly. 我是单元测试的新手,所以请原谅我,如果我无法正确解释这个问题。 I am reading a book "The art of Unit Testing 2nd Edition" and trying to implement unit testing in my project.
我正在读一本书“单元测试第二版的艺术”,并试图在我的项目中实施单元测试。 I am currently stuck or confused when testing using mocking (using NSubstitute as the mocking framework).
在使用模拟测试时(使用NSubstitute作为模拟框架),我目前陷入困境或困惑。
Here is my scenario: 这是我的场景:
I have two interfaces ICommand
and IUser
我有两个接口
ICommand
和IUser
public interface ICommand
{
string execute();
}
public interface IUserCalendar
{
string LoadCalendar();
}
I have a class LoadCalendar
which implements ICommand
: 我有一个实现
ICommand
的类LoadCalendar
:
public class LoadCalendar : ICommand
{
private IUserCalendar user;
public string execute()
{
return this.user.LoadCalendar();
}
public LoadCalendar(IUserCalendar obj)
{
this.user = obj;
}
}
ViewCalendar
implements IUserCalendar
: ViewCalendar
实现了IUserCalendar
:
public class Viewer : IUserCalendar
{
public string LoadCalendar()
{
return "Viewer Load Calendar Called";
}
}
Using an agent class I am invoking command for specific request. 使用代理类我正在调用特定请求的命令。 (Here I am showing only one request
LoadCalendar
for one user viewer but I have more command and more users) (这里我只为一个用户查看器显示一个请求
LoadCalendar
但我有更多命令和更多用户)
My client has an invoker object that invokes the command for specific user. 我的客户端有一个调用对象,可以为特定用户调用该命令。
public class Client
{
public Client()
{ }
public string LoadCalendar(ICommand cmd)
{
Invoker invoker = new Invoker(cmd);
return invoker.execute();
}
}
Now I like to test the client class that when it calls for specific user it should return proper object or message. 现在我喜欢测试客户端类,当它调用特定用户时,它应该返回适当的对象或消息。
[Test]
public void client_Load_Calendar_Administrator()
{
IUserCalendar calanedar = Substitute.For<IUserCalendar>();
ICommand cmd = Substitute.For<ICommand>(calanedar);
Client c = new Client();
c.LoadCalendar(cmd, calanedar).Returns(Arg.Any<string>());
}
I don't know where I am doing wrong and it's throwing an error. 我不知道我在哪里做错了,这是一个错误。
NSubstitute.Exceptions.SubstituteException : Can not provide constructor arguments when substituting for an interface.
NSubstitute.Exceptions.SubstituteException:替换接口时无法提供构造函数参数。
Any help is really appreciated. 任何帮助都非常感谢。 Sorry for long question.
对不起,对不起。
The error you're getting: 你得到的错误:
Can not provide constructor arguments when substituting for an interface.
替换接口时无法提供构造函数参数。
Is telling you exactly what's wrong. 告诉你到底出了什么问题。
You're passing in constructor arguments here: 你在这里传递构造函数参数:
ICommand cmd = Substitute.For<ICommand>(calanedar);
Of course, interfaces never have a constructor. 当然,接口永远不会有构造函数。 You're trying to interact with your ICommand interface as if it were your concrete
LoadCalendar
implementation of it. 您正在尝试与ICommand接口进行交互,就好像它是您的具体
LoadCalendar
实现一样。
Furthermore, to be able to unit test a class you always want to have a default (parameterless) constructor. 此外,为了能够对一个类进行单元测试,你总是希望有一个默认的(无参数)构造函数。 Many mocking frameworks actually require this.
许多模拟框架实际上需要这个。
In this case you should probably test against the concrete class and mock/substitute the classes that it uses. 在这种情况下,您应该测试具体类并模拟/替换它使用的类。
Either that, or you only substitute ICommand
simply to have it return a pre-set (string) value. 要么就是这样,要么只替换
ICommand
使其返回预设(字符串)值。 Then you can proceed to verify if the code that consumes your command, actually invokes it and/or does the correct thing with the value it returns. 然后,您可以继续验证使用命令的代码是否实际调用它和/或使用返回的值执行正确的操作。
To illustrate: 为了显示:
[Test]
public void client_Load_Calendar_Administrator()
{
// You are substituting (mocking) the IUserCalendar here, so to test your command
// use the actual implementation
IUserCalendar calendar = Substitute.For<IUserCalendar>();
ICommand cmd = new LoadCalendar(calendar):
// Let the IUserCalendar.LoadCalendar() return a certain string
// Then Assert/Verify that cmd.Execute() returns that same string
}
That's the point of unit testing: you test the smallest piece of functionality by mocking all dependencies. 这就是单元测试的重点:通过模拟所有依赖项来测试最小的功能。 Otherwise it's an integration test.
否则它是一个集成测试。
To test your client: 测试您的客户:
[Test]
public void client_Load_Calendar_Administrator()
{
ICommand cmd = Substitute.For<ICommand>();
Client c = new Client();
// Let your command return a certain string
// Then verify that your calendar returns that same string
}
EDIT: In case you're interested, the method in NSubstitute that throws this exception : 编辑:如果您感兴趣, NSubstitute中抛出此异常的方法 :
private void VerifyNoConstructorArgumentsGivenForInterface(object[] constructorArguments)
{
if (constructorArguments != null && constructorArguments.Length > 0)
{
throw new SubstituteException("Can not provide constructor arguments when substituting for an interface.");
}
}
They're pretty clear about it: no constructor arguments for an interface substitute, no matter what. 他们对此非常清楚:无论如何都没有接口替换的构造函数参数。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.