Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/unit-testing/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何在基类方法中接收单元测试委托?_C#_Unit Testing_Delegates_Nunit_Nsubstitute - Fatal编程技术网

C# 如何在基类方法中接收单元测试委托?

C# 如何在基类方法中接收单元测试委托?,c#,unit-testing,delegates,nunit,nsubstitute,C#,Unit Testing,Delegates,Nunit,Nsubstitute,我目前有一个基本服务类,我的所有服务都会扩展它。这是其中一种方法的外观: protected internal virtual T PerformServiceOperationWithExceptionHandling<T>(Func<T> func) { try { return func.Invoke(); } ..

我目前有一个基本服务类,我的所有服务都会扩展它。这是其中一种方法的外观:

   protected internal virtual T PerformServiceOperationWithExceptionHandling<T>(Func<T> func)
        {
            try
            {
                return func.Invoke();
            }

            ...
        }
我想测试AddGuest并确保“AddGuestLogic”作为基本方法中的参数传递?如何使用nSubstitute和nUnit实现这一点。我认为这不可能

================================================

我最终使用了以下代码:

    [Test]
    public void AddGuest_WhenCalled_PerformsAddGuestLogicWithExceptionHandling()
    {
        Func<AddGuestResponse> addGuestLogic = null;
        _guestService.PerformServiceOperationWithExceptionHandling(Arg.Do<Func<AddGuestResponse>>(arg => addGuestLogic = arg));
        var addGuestRequest = new AddGuestRequest();
        _guestService.AddGuest(addGuestRequest);
        _guestService.ClearReceivedCalls();

        addGuestLogic.Invoke();

        _guestService.Received().AddGuestLogic(addGuestRequest);
    }
[测试]
public void AddGuest\u调用时\u performsaddguestlogicWith exception handling()
{
Func addGuestLogic=null;
_guestService.PerformServiceOperationWithExceptionHandling(Arg.Do(Arg=>addGuestLogic=Arg));
var addGuestRequest=new addGuestRequest();
_guestService.AddGuest(addGuestRequest);
_guestService.ClearReceivedCalls();
addGuestLogic.Invoke();
_guestService.Received().AddGuestLogic(addGuestRequest);
}

_guestService是在我的设置方法中创建的,如下所示:Substitute.ForPartsOf()

简短的回答-你不应该。单元测试是关于测试被测试方法的行为,而不是实现细节

长答覆: 类内部如何工作并不重要,只要它产生预期的结果


您需要在最后一个类上测试您的公共方法,看看它是否如预期的那样工作。孤立地测试基类/抽象类证明不了什么。

简单回答-你不应该这样做。单元测试是关于测试被测试方法的行为,而不是实现细节

长答覆: 类内部如何工作并不重要,只要它产生预期的结果


您需要在最后一个类上测试您的公共方法,看看它是否如预期的那样工作。孤立地测试基类/抽象类证明不了什么。

简单回答-你不应该这样做。单元测试是关于测试被测试方法的行为,而不是实现细节

长答覆: 类内部如何工作并不重要,只要它产生预期的结果


您需要在最后一个类上测试您的公共方法,看看它是否如预期的那样工作。孤立地测试基类/抽象类证明不了什么。

简单回答-你不应该这样做。单元测试是关于测试被测试方法的行为,而不是实现细节

长答覆: 类内部如何工作并不重要,只要它产生预期的结果


您需要在最后一个类上测试您的公共方法,看看它是否如预期的那样工作。单独测试基类/抽象类证明不了什么。

我支持Sunny Milenov的答案,但我会建议您进一步修改设计。我了解到,当遵循组合而不是继承的原则时,测试基类行为的许多头痛问题就会消失

也就是说,如果您将基类重构为协作者,并将其注入到服务的构造函数中,那么您可以单独测试它,并在服务的测试中模拟它。不用担心测试抽象基类或在所有服务测试中测试相同的异常处理

您将测试协作者是否在协作者的测试中正确调用func

在服务的测试中,您可以模拟协作者立即返回Func的结果:

 [Test]
 public void ServiceLogicIsExecuted()
 {
     var collaborator = Substitute.For<ICollaborator>();

     //Tell the test double to return the Func's result. You'd probably want to do this in the setup method.
     collaborator.PerformServiceOperation(Arg.Any<Func<int>>()).Returns(x => ((Func<int>)x[0]).Invoke());

     var sut = new Service(collaborator);

     var result = sut.CalculateSomething();

     Assert.That(result, Is.EqualTo(99));
 }

 public class Service
 {
     private readonly ICollaborator _collaborator;

     public Service(ICollaborator collaborator)
     {
         _collaborator = collaborator;
     }

     public int CalculateSomething()
     {
         return _collaborator.PerformServiceOperation(ExecuteLogic);
     }

     private static int ExecuteLogic()
     {
         return 99;
     }
 }

 public interface ICollaborator
 {
     T PerformServiceOperation<T>(Func<T> func);
 }
[测试]
public void ServiceLogicIsExecuted()
{
var collaborator=Substitute.For();
//告诉test double返回Func的结果。您可能希望在setup方法中执行此操作。
collaborator.PerformServiceOperation(Arg.Any())。返回(x=>((Func)x[0]).Invoke());
var sut=新服务(合作者);
var result=sut.calculateMething();
断言(结果为.EqualTo(99));
}
公务舱服务
{
专用只读ICollaborator\u合作者;
公共服务(ICollaborator合作者)
{
_合作者=合作者;
}
公共int计算方法()
{
return _collaborator.PerformServiceOperation(ExecuteLogic);
}
私有静态int ExecuteLogic()
{
返回99;
}
}
公共接口ICollaborator
{
T执行服务操作(Func Func);
}

我赞同Sunny Milenov的回答,但我会进一步建议您更改设计。我了解到,当遵循组合而不是继承的原则时,测试基类行为的许多头痛问题就会消失

也就是说,如果您将基类重构为协作者,并将其注入到服务的构造函数中,那么您可以单独测试它,并在服务的测试中模拟它。不用担心测试抽象基类或在所有服务测试中测试相同的异常处理

您将测试协作者是否在协作者的测试中正确调用func

在服务的测试中,您可以模拟协作者立即返回Func的结果:

 [Test]
 public void ServiceLogicIsExecuted()
 {
     var collaborator = Substitute.For<ICollaborator>();

     //Tell the test double to return the Func's result. You'd probably want to do this in the setup method.
     collaborator.PerformServiceOperation(Arg.Any<Func<int>>()).Returns(x => ((Func<int>)x[0]).Invoke());

     var sut = new Service(collaborator);

     var result = sut.CalculateSomething();

     Assert.That(result, Is.EqualTo(99));
 }

 public class Service
 {
     private readonly ICollaborator _collaborator;

     public Service(ICollaborator collaborator)
     {
         _collaborator = collaborator;
     }

     public int CalculateSomething()
     {
         return _collaborator.PerformServiceOperation(ExecuteLogic);
     }

     private static int ExecuteLogic()
     {
         return 99;
     }
 }

 public interface ICollaborator
 {
     T PerformServiceOperation<T>(Func<T> func);
 }
[测试]
public void ServiceLogicIsExecuted()
{
var collaborator=Substitute.For();
//告诉test double返回Func的结果。您可能希望在setup方法中执行此操作。
collaborator.PerformServiceOperation(Arg.Any())。返回(x=>((Func)x[0]).Invoke());
var sut=新服务(合作者);
var result=sut.calculateMething();
断言(结果为.EqualTo(99));
}
公务舱服务
{
专用只读ICollaborator\u合作者;
公共服务(ICollaborator合作者)
{
_合作者=合作者;
}
公共int计算方法()
{
return _collaborator.PerformServiceOperation(ExecuteLogic);
}
私有静态int ExecuteLogic()
{
返回99;
}
}
公共接口ICollaborator
{
T执行服务操作(Func Func);
}