C# 在nsubstitute接收方法的参数匹配器中匹配func委托

C# 在nsubstitute接收方法的参数匹配器中匹配func委托,c#,unit-testing,nsubstitute,argument-matching,C#,Unit Testing,Nsubstitute,Argument Matching,我试图检查一个方法在类的模拟实例上是否被调用了特定次数。问题是该方法有一个func委托,但该委托不匹配 我有以下情况: public interface ISomeService: IService { Task CleanupMethod(CancellationToken cancellationToken); } public interface I { Task invokedMethod(string aName, Func<IService, Task>

我试图检查一个方法在类的模拟实例上是否被调用了特定次数。问题是该方法有一个
func委托
,但该委托不匹配

我有以下情况:

public interface ISomeService: IService
{
    Task CleanupMethod(CancellationToken cancellationToken);
}

public interface I
{
    Task invokedMethod(string aName, Func<IService, Task> action);
}


public class ClassGoingToBeUnitTested
{
    // instance of I
    private I instanceOfI;

    // a list of names.
    private static readonly string[] serviceNames =
    {
        "Name1",
        "Name2"
    };

    // constructor
    public ClassGoingToBeUnitTested(I passedInstance)
    {
        this.instanceOfI = passedInstance;
    }


    public void methodToBeUnitTested(object cancellationToken)
    {
        // my logic here

        // here I am calling invokedMethod method to known number of times.
        // something like this.

        try
        {
            IEnumerable<Task> someTasks = serviceNames.Select(
                name => this.instanceOfI.invokedMethod(
                    name,
                    service => ((ISomeService)service).CleanupMethod((CancellationToken)cancellationToken)
                    ));

            // here I run the tasks
            Task.WaitAll(someTasks.ToArray());

        }
        catch
        {
            // proper catching of exceptions
        }

        // other logic
    }
}


[TestClass]
public class ClassGoingToBeUnitTestedTest
{
    // mock of I interface
    private I IMock;

    // ClassGoingToBeUnitTested object
    ClassGoingToBeUnitTested classGoingToBeUnitTested;

    [TestInitialize]
    public void init()
    {
        this.IMock = Substitute.For<I>();
        this.classGoingToBeUnitTested = new ClassGoingToBeUnitTested(this.IMock);
    }


    [TestMethod]
    public void methodToBeUnitTested_Success()
    {
        // Arrange
        var cancellationTokenSource = new CancellationTokenSource();

        // Act
        this.classGoingToBeUnitTested.methodToBeUnitTested(cancellationTokenSource.Token);

        // Assert
        // this is throwing exception.
        this.IMock.Received(1).invokedMethod(
             "Name1",
             service => ((ISomeService)service).CleanupMethod((CancellationToken)cancellationTokenSource.Token)); // problem lies in this line.

    }
}
公共接口服务:iSeries设备
{
任务清理方法(CancellationToken CancellationToken);
}
公共接口I
{
任务调用方法(字符串名称、函数操作);
}
公共类将要进行测试
{
//I的实例
一等兵;
//名单。
私有静态只读字符串[]serviceNames=
{
“名称1”,
“名称2”
};
//建造师
公共类将进行未经测试(I通过状态)
{
this.instanceOfI=passedInstance;
}
public void methodToBeUnitTested(对象取消令牌)
{
//我的逻辑在这里
//在这里,我调用invokedMethod方法的次数是已知的。
//像这样的。
尝试
{
IEnumerable someTasks=服务名称。选择(
name=>this.instanceOfI.invokedMethod(
名称
服务=>((ISomeService)服务).CleanupMethod((CancellationToken)CancellationToken)
));
//我在这里运行任务
Task.WaitAll(someTasks.ToArray());
}
抓住
{
//正确捕获异常
}
//其他逻辑
}
}
[测试类]
公共类将进行未经测试的测试
{
//I接口的模拟
二等兵伊莫克;
//类将成为受试对象
类别将进行未经测试类别将进行未经测试;
[测试初始化]
公共void init()
{
this.IMock=替换.For();
this.classgoingtobeunitested=新类goingtobeunitested(this.IMock);
}
[测试方法]
public void MethodToBeuntTested_Success()方法
{
//安排
var cancellationTokenSource=新的cancellationTokenSource();
//表演
this.classGoingToBeUnitTested.methodToBeUnitTested(cancellationTokenSource.Token);
//断言
//这是抛出异常。
this.IMock.Received(1).invokedMethod(
“名称1”,
service=>((ISomeService)service.CleanupMethod((CancellationToken)cancellationTokenSource.Token));//问题在于此行。
}
}

在上面的代码中,如果我将
((ISomeService)service).CleanupMethod((CancellationToken)cancellationTokenSource.Token))
更改为
Arg。任何我都通过使用
调用解决了这个问题。我首先模拟了
invokedMethod
的行为,以便在调用时调用模拟的
serviceInstanceMock
,然后检查
serviceInstanceMock
本身调用
CleanupMethod
的次数

[TestClass]
public class ClassGoingToBeUnitTestedTest
{
    // mock of I interface
    private I IMock;

    // mock of ISomeService
    private ISomeService someServiceMockInstance;

    // ClassGoingToBeUnitTested object
    ClassGoingToBeUnitTested classGoingToBeUnitTested;

    [TestInitialize]
    public void init()
    {
        this.IMock = Substitute.For<I>();
        this.ISomeService = Substitute.For<ISomeService>();
        this.classGoingToBeUnitTested = new ClassGoingToBeUnitTested(this.IMock);
    }


    [TestMethod]
    public void methodToBeUnitTested_Success()
    {
        // Arrange
        var cancellationTokenSource = new CancellationTokenSource();
        this.IMock.invokedMethod(
            Arg.Any<string>,
            Arg.Do<Func<IService, Task>(x => x.Invoke(this.someServiceMockInstance)));

        // Act
        this.classGoingToBeUnitTested.methodToBeUnitTested(cancellationTokenSource.Token);

        // Assert
        this.IMock.Received(1).invokedMethod(
             "Name1",
             Arg.Any<Func<IService, Task>()); // changed this

        this.IMock.Received(1).invokedMethod(
             "Name2",
             Arg.Any<Func<IService, Task>()); // added this as well

        // adding to check the Received call on the service instance
        this.someServiceMockInstance.Received(2).CleanupMethod(cancellationTokenSource.Token);
    }
}
[TestClass]
公共类将进行未经测试的测试
{
//I接口的模拟
二等兵伊莫克;
//模拟服务
私有服务someServiceMockInstance;
//类将成为受试对象
类别将进行未经测试类别将进行未经测试;
[测试初始化]
公共void init()
{
this.IMock=替换.For();
this.isomService=替换.For();
this.classgoingtobeunitested=新类goingtobeunitested(this.IMock);
}
[测试方法]
public void MethodToBeuntTested_Success()方法
{
//安排
var cancellationTokenSource=新的cancellationTokenSource();
this.IMock.invokedMethod(
Arg.任何,
Arg.Do x.Invoke(this.someServiceMockInstance));
//表演
this.classGoingToBeUnitTested.methodToBeUnitTested(cancellationTokenSource.Token);
//断言
this.IMock.Received(1).invokedMethod(
“名称1”,

Arg.AnyI在的答案中列出了一些其他选项。该答案适用于
表达式
值,但同样适用于标准lambda函数。当然。我会检查此选项。谢谢!