简体   繁体   English

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

[英]How to unit test delegate was received in base class method?

I currently have a base service class that all my services extend. 我目前有一个基础服务类,所有服务都可以扩展。 This is what one of the methods look like: 这是其中一种方法的样子:

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

            ...
        }

In the derived classes I call the method like this: 在派生类中,我这样调用方法:

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

I want to test AddGuest and ensure "AddGuestLogic" is being passed as a parameter in the base method? 我要测试AddGuest并确保在基本方法中将“ AddGuestLogic”作为参数传递? How do I achieve this with nSubstitute and nUnit. 如何使用nSubstitute和nUnit实现此目的。 I don't think its possible? 我认为这不可能吗?

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

I ended up using the following code: 我最终使用了以下代码:

    [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);
    }

The _guestService is created in my setup method as follows: Substitute.ForPartsOf(); _guestService是在我的设置方法中创建的,如下所示:Substitute.ForPartsOf();

I second Sunny Milenov's answer, but would go one step further by advising you to change your design. 我赞同Sunny Milenov的回答,但建议您更改设计会更进一步。 I have learned the hard way that many of these headaches with testing base class behavior go away when you follow the principle of composition over inheritance. 我已经学会了很难的方法,当您遵循组成而不是继承的原理时,测试基本类行为的许多头痛都会消失。

Ie, if you refactor your base class to a collaborator, which you inject into your services' constructor, you can test that in isolation and mock it in your services' tests. 即,如果您将基类重构为协作者,并注入到服务的构造函数中,则可以单独进行测试,并在服务的测试中对其进行模拟。 No worrying about testing an abstract base class or testing the same exception handling in all of your services' tests. 无需担心在所有服务的测试中测试抽象基类或测试相同的异常处理。

You would test that the collaborator correctly invokes the func in the collaborator's tests. 您将在协作者的测试中测试协作者是否正确调用了func。

In the services' tests you can just mock the collaborator to return the Func's result right away: 在服务的测试中,您可以模拟合作者立即返回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);
 }

Short answer - you shouldn't. 简短的答案-您不应该。 Unit testing is about testing the behavior of the tested method, not the implementation details. 单元测试是关于测试所测试方法的行为,而不是实现细节。

Long answer: It doesn't matter how the class internally works, as far as it produces the expected results. 长答案:类内部如何工作并不重要,只要它产生预期的结果即可。

You need to test your public method on the final class and see if this works as expected. 您需要在最终类上测试您的公共方法,并查看其是否按预期工作。 Testing a base/abstract class in isolation proves nothing. 孤立地测试基类/抽象类不会证明任何事情。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM