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

时间:2015-03-09 05:20:26

标签: c# unit-testing delegates nunit nsubstitute

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

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

            ...
        }

在派生类中,我调用这样的方法:

    public AddGuestResponse AddGuest(AddGuestRequest addGuestRequest)
    {
        return PerformServiceOperationWithExceptionHandling(() => AddGuestLogic(addGuestRequest));
    }

我想测试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);
    }

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

2 个答案:

答案 0 :(得分:2)

我是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);
 }

答案 1 :(得分:1)

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

答案很长: 只要它产生预期的结果,课程内部的工作方式并不重要。

您需要在最终类上测试您的公共方法,看看它是否按预期工作。孤立地测试基类/抽象类证明什么都没有。