简体   繁体   English

单元测试Void方法调用另一个void,启动Task()

[英]Unit testing Void method which calls another void, starts Task()

I'm looking for some advice on writing some unit tests for the code below. 我正在寻找一些关于为下面的代码编写一些单元测试的建议。 Implementation aside (it's not my code, but I've been tasked to retroactively write some tests for it) could someone suggest how I might test this? 抛开实现(这不是我的代码,但我的任务是追溯性地为它编写一些测试)有人会建议我如何测试它吗? I'm not using nUnit or a similar framework; 我没有使用nUnit或类似的框架; I am using the testing tools built into Visual Studio. 我正在使用Visual Studio内置的测试工具。

I'm fairly new to writing unit tests, but I imagine I should at least test the following: 我是编写单元测试的新手,但我想我至少应该测试以下内容:

  • Valid response passed into SaveFormBrokerResponse() method 传递给SaveFormBrokerResponse()方法的有效响应
  • Test for valid exceptions thrown by the catch() 测试catch()抛出的有效异常
  • Testing the started Task , but not sure how to do this 测试已启动的Task ,但不知道如何执行此操作

I've stripped just a bit out of this function, mostly to do with instantiation and population of some objects: 我已经剥离了这个函数,主要是与实例化和一些对象的填充:

public void SaveResponse(IForm form, bool isLive, HttpRequestBase request)
{
    try
    {
        var response = new FormBrokerResponses();
        // Initialize some vars on response

        using (var memory = new MemoryStream())
        {
            var serializer = new DataContractSerializer(typeof(FormKeyValue[]));
            serializer.WriteObject(memory, request.Form.AllKeys.Select(r => new FormKeyValue(r, request.Form[r])).ToArray());
            memory.Flush();
            memory.Seek(0, SeekOrigin.Begin);
            response.Values = Encoding.UTF8.GetString(memory.ToArray());
        }

        _dataHandler.SaveFormBrokerResponses(response);
    }
    catch (Exception ex)
    {
        throw new Exception("boom explosions");
    }

    Task.Factory.StartNew(() => DispatchFormResponseViaEmail(form, isLive, request.Form.AllKeys.ToDictionary(r => r, r => (object)request.Form[r])));
}

I realize that testing void implementations is tricky and questionable and that there are some integration test concerns here, but that said I can't (currently) change the implementation and need to write tests for what I have. 我意识到测试void实现是棘手和可疑的,并且这里有一些集成测试问题,但是说我不能(当前)改变实现并需要为我所拥有的内容编写测试。

You can't. 你不能。 You've created a method that fires off an asynchronous operation and then doesn't expose any means of observing the completion/results of that operation to the caller. 您已经创建了一个方法来触发异步操作,然后不会向调用者公开任何观察该操作的完成/结果的方法。 There are lots of ways of doing this (returning a task, accepting a callback, an event, etc.) but you need to do something for the caller to be able to observe the results of the asynchronous operation. 有很多方法可以做到这一点(返回任务,接受回调,事件等),但是你需要为调用者做些事情才能观察异步操作的结果。 If the method doesn't expose anything, then there is nothing that the caller can reliably do. 如果该方法没有暴露任何东西,那么调用者无法可靠地执行任何操作。

If you are allowed to make slight modifications to the code I would do the following which is just a small change anyway : 如果您允许对代码稍作修改,我会执行以下操作,这只是一个小改动:

public void SaveResponse(IForm form, bool isLive, HttpRequestBase request)
{
    try
    {
        var response = new FormBrokerResponses();
        // Initialize some vars on response

        using (var memory = new MemoryStream())
        {
            var serializer = new DataContractSerializer(typeof(FormKeyValue[]));
            serializer.WriteObject(memory, request.Form.AllKeys.Select(r => new FormKeyValue(r, request.Form[r])).ToArray());
            memory.Flush();
            memory.Seek(0, SeekOrigin.Begin);
            response.Values = Encoding.UTF8.GetString(memory.ToArray());
        }

        _dataHandler.SaveFormBrokerResponses(response);
    }
    catch (Exception ex)
    {
        throw new Exception("boom explosions");
    }

    Dispatch(form,isLive,request);
}

virtual void Dispatch(IForm form, bool isLive, HttpRequestBase request){
    Task.Factory.StartNew(() => DispatchFormResponseViaEmail(form, isLive, request.Form.AllKeys.ToDictionary(r => r, r => (object)request.Form[r])));
}

I don't know what this class is named so suppose the class is named DutClass, you can now derive a different implementation of that class as following: 我不知道这个类的名称是什么,所以假设该类名为DutClass,您现在可以得到该类的不同实现,如下所示:

public class UnitTestClass : DutClass{
    override Dispatch(){
        //don't do anything or set a state variable that this method was called
    }
}

Then instead of testing the DutClass you test the UnitTextClass which has a different implementation of the Dispatch method and does not start a Task at all. 然后,不是测试DutClass,而是测试UnitTextClass,它具有Dispatch方法的不同实现,并且根本不启动任务。 You can then test that in fact this method was called, test for the exceptions and so on. 然后,您可以测试实际调用此方法,测试异常等。

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

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