Unit testing 使用委托/lambda参数的存根方法调用
我有一个如下所示的接口和类:Unit testing 使用委托/lambda参数的存根方法调用,unit-testing,lambda,mocking,rhino-mocks,func,Unit Testing,Lambda,Mocking,Rhino Mocks,Func,我有一个如下所示的接口和类: public interface IServiceFacade { TResult Execute<TResult>(Func<IService, TResult> operation); } public class ServiceFacade : IServiceFacade { private readonly string endpoint = "EndPoint"; public TResult Exe
public interface IServiceFacade
{
TResult Execute<TResult>(Func<IService, TResult> operation);
}
public class ServiceFacade : IServiceFacade
{
private readonly string endpoint = "EndPoint";
public TResult Execute<TResult>(Func<IService, TResult> operation)
{
// Call to remote WCF service that results in a TResult
return TResult;
}
}
public class ServiceConsumer
{
public ServiceConsumer(IServiceFacade serviceFacade)
{
var returnInteger1 = serviceFacade.Execute(service => service.Method1("StringArgument1"));
var returnInteger2 = serviceFacade.Execute(service => service.Method1("StringArgument2"));
}
}
在我的单元测试中,我想将第一个调用的returnvalue存根为1,第二个调用的returnvalue存根为2
示例测试方法
[Test]
public void TestMethod()
{
var serviceFacadeStub = MockRepository.GenerateStub<IServiceFacade>();
serviceFacadeStub.Stub(call => call.Execute(Arg<Func<IService, int>.Matches(?))).Return(1);
serviceFacadeStub.Stub(call => call.Execute(Arg<Func<IService, int>.Matches(?))).Return(2);
var sut = new ServiceConsumer(serviceFacadeStub);
}
[测试]
公共void TestMethod()
{
var serviceFacadeStub=MockRepository.generateSub();
serviceFacadeStub.Stub(call=>call.Execute(Arg call.Execute)(Arg在大多数情况下,使用Func
/Action
模拟方法有点棘手(在我知道的任何模拟框架中…)
通常,您必须执行给定的Func
/操作
,然后结果应该会影响被测单元的其余部分
以下代码片段显示了解决问题的简单方法:
[Test]
public void TestMethod(
{
var fakeService = MockRepository.GenerateStub<IService>();
fakeService.Stub(x => x.Method1("StringArgument1")).Return(1);
fakeService.Stub(x => x.Method1("StringArgument2")).Return(2);
var serviceFacadeStub = MockRepository.GenerateStub<IServiceFacade>();
serviceFacadeStub.Stub(call => call.Execute(Arg<Func<IService, int>>.Is.Anything))
.WhenCalled(invocation =>
{
var func = (Func<IService, int>)invocation.Arguments[0];
invocation.ReturnValue = func(fakeService);
}).Return(0);
var shouldBeOne = serviceFacadeStub.Execute(service => service.Method1("StringArgument1"));
var shouldBeTwo = serviceFacadeStub.Execute(service => service.Method1("StringArgument2"));
Assert.AreEqual(1, shouldBeOne);
Assert.AreEqual(2, shouldBeTwo);
}
[测试]
公开无效测试方法(
{
var fakeService=MockRepository.generateSub();
存根(x=>x.Method1(“StringArgument1”)).Return(1);
存根(x=>x.Method1(“StringArgument2”)).Return(2);
var serviceFacadeStub=MockRepository.generateSub();
存根(call=>call.Execute(Arg.Is.Anything))
.WhenCalled(调用=>
{
var func=(func)invocation.Arguments[0];
invocation.ReturnValue=func(fakeService);
}).返回(0);
var shouldBeOne=serviceFacadeStub.Execute(service=>service.Method1(“StringArgument1”);
var shouldBeTwo=serviceFacadeStub.Execute(service=>service.Method1(“StringArgument2”);
断言.AreEqual(1,应该是1);
断言。等于(2,应为2);
}
我使用fakeService
执行lambda,然后基于给定参数返回结果。
另一种选择是像你那样使用匹配
,但是你必须使用反射来分析lambda…(它要复杂得多…)如果其他人也有同样的问题,我会发布我的想法。我开始使用NSubstitute,这很简单
var serviceSub = Substitute.For<IService>();
serviceSub.Method1(Arg.Is<string>(arg => arg == "StringArgument1")).Returns(1);
serviceSub.Method1(Arg.Is<string>(arg => arg == "StringArgument2")).Returns(2);
var mobileServiceFacadeSub = Substitute.For<IServiceFacade>();
mobileServiceFacadeSub.Execute(Arg.InvokeDelegate<Func<IService, ICollection<TResult>>>(serviceSub));
var serviceSub=Substitute.For();
serviceSub.Method1(Arg.Is(Arg=>Arg==“StringArgument1”))。返回(1);
serviceSub.Method1(Arg.Is(Arg=>Arg==“StringArgument2”))。返回(2);
var mobileseservicefacadesub=替换为();
mobileseservicefacadesub.Execute(Arg.InvokeDelegate(serviceSub));