使用 Nsubstitute 进行模拟但出现错误
Using Nsubstitute for mocking but getting an error
我是单元测试的新手,如果我无法正确解释这个问题,请原谅我。我正在阅读一本书 "The art of Unit Testing 2nd Edition" 并尝试在我的项目中实施单元测试。我目前在使用模拟(使用 NSubstitute 作为模拟框架)进行测试时感到困惑或困惑。
这是我的场景:
我有两个接口 ICommand
和 IUser
public interface ICommand
{
string execute();
}
public interface IUserCalendar
{
string LoadCalendar();
}
我有一个 class LoadCalendar
实现 ICommand
:
public class LoadCalendar : ICommand
{
private IUserCalendar user;
public string execute()
{
return this.user.LoadCalendar();
}
public LoadCalendar(IUserCalendar obj)
{
this.user = obj;
}
}
ViewCalendar
实施 IUserCalendar
:
public class Viewer : IUserCalendar
{
public string LoadCalendar()
{
return "Viewer Load Calendar Called";
}
}
使用代理 class 我正在为特定请求调用命令。 (这里我只显示一个请求 LoadCalendar
一个用户查看器,但我有更多的命令和更多的用户)
我的客户端有一个为特定用户调用命令的调用程序对象。
public class Client
{
public Client()
{ }
public string LoadCalendar(ICommand cmd)
{
Invoker invoker = new Invoker(cmd);
return invoker.execute();
}
}
现在我想测试客户端 class 当它调用特定用户时它应该 return 正确的对象或消息。
[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>());
}
我不知道我哪里做错了,它抛出了一个错误。
NSubstitute.Exceptions.SubstituteException : Can not provide constructor arguments when substituting for an interface.
非常感谢任何帮助。抱歉,问题很长。
您遇到的错误:
Can not provide constructor arguments when substituting for an interface.
告诉你到底哪里出了问题。
您在此处传递构造函数参数:
ICommand cmd = Substitute.For<ICommand>(calanedar);
当然,接口从来没有构造函数。您正在尝试与 ICommand 接口进行交互,就好像它是您的具体 LoadCalendar
实现一样。
此外,为了能够对 class 进行单元测试,您总是希望有一个默认(无参数)构造函数。许多模拟框架实际上需要这个。
在这种情况下,您可能应该针对 class 和 mock/substitute 它 使用的 class 进行测试。
要么,要么你只替换 ICommand
只是让它 return 一个预设(字符串)值。然后您可以继续验证使用您的命令的代码是否实际调用它 and/or 使用它的值 returns.
做正确的事情
举例说明:
[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
}
这就是单元测试的要点:您通过模拟所有依赖项来测试最小的功能块。否则就是集成测试。
测试你的客户端:
[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
}
编辑: 如果您有兴趣,the method in NSubstitute that throws this exception:
private void VerifyNoConstructorArgumentsGivenForInterface(object[] constructorArguments)
{
if (constructorArguments != null && constructorArguments.Length > 0)
{
throw new SubstituteException("Can not provide constructor arguments when substituting for an interface.");
}
}
他们对此非常清楚:无论如何,接口替代品都没有构造函数参数。
我是单元测试的新手,如果我无法正确解释这个问题,请原谅我。我正在阅读一本书 "The art of Unit Testing 2nd Edition" 并尝试在我的项目中实施单元测试。我目前在使用模拟(使用 NSubstitute 作为模拟框架)进行测试时感到困惑或困惑。
这是我的场景:
我有两个接口 ICommand
和 IUser
public interface ICommand
{
string execute();
}
public interface IUserCalendar
{
string LoadCalendar();
}
我有一个 class LoadCalendar
实现 ICommand
:
public class LoadCalendar : ICommand
{
private IUserCalendar user;
public string execute()
{
return this.user.LoadCalendar();
}
public LoadCalendar(IUserCalendar obj)
{
this.user = obj;
}
}
ViewCalendar
实施 IUserCalendar
:
public class Viewer : IUserCalendar
{
public string LoadCalendar()
{
return "Viewer Load Calendar Called";
}
}
使用代理 class 我正在为特定请求调用命令。 (这里我只显示一个请求 LoadCalendar
一个用户查看器,但我有更多的命令和更多的用户)
我的客户端有一个为特定用户调用命令的调用程序对象。
public class Client
{
public Client()
{ }
public string LoadCalendar(ICommand cmd)
{
Invoker invoker = new Invoker(cmd);
return invoker.execute();
}
}
现在我想测试客户端 class 当它调用特定用户时它应该 return 正确的对象或消息。
[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>());
}
我不知道我哪里做错了,它抛出了一个错误。
NSubstitute.Exceptions.SubstituteException : Can not provide constructor arguments when substituting for an interface.
非常感谢任何帮助。抱歉,问题很长。
您遇到的错误:
Can not provide constructor arguments when substituting for an interface.
告诉你到底哪里出了问题。
您在此处传递构造函数参数:
ICommand cmd = Substitute.For<ICommand>(calanedar);
当然,接口从来没有构造函数。您正在尝试与 ICommand 接口进行交互,就好像它是您的具体 LoadCalendar
实现一样。
此外,为了能够对 class 进行单元测试,您总是希望有一个默认(无参数)构造函数。许多模拟框架实际上需要这个。
在这种情况下,您可能应该针对 class 和 mock/substitute 它 使用的 class 进行测试。
要么,要么你只替换 ICommand
只是让它 return 一个预设(字符串)值。然后您可以继续验证使用您的命令的代码是否实际调用它 and/or 使用它的值 returns.
举例说明:
[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
}
这就是单元测试的要点:您通过模拟所有依赖项来测试最小的功能块。否则就是集成测试。
测试你的客户端:
[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
}
编辑: 如果您有兴趣,the method in NSubstitute that throws this exception:
private void VerifyNoConstructorArgumentsGivenForInterface(object[] constructorArguments)
{
if (constructorArguments != null && constructorArguments.Length > 0)
{
throw new SubstituteException("Can not provide constructor arguments when substituting for an interface.");
}
}
他们对此非常清楚:无论如何,接口替代品都没有构造函数参数。