从控制台应用程序调用但未从NUnit测试调用时,库工作

时间:2018-12-17 14:57:43

标签: c# nunit .net-standard .net-framework-version

我正在尝试为我正在研究的项目评估工作流库。可以在github workflow-core上找到该库。

为了开始工作,我试图构建一个简单的工作流,该工作流只是将一些文本写入文件中。奇怪的是,当从控制台应用程序项目中调用时,工作流可以正常工作。但是,当我在NUnit测试中使用相同的代码并运行它时,它不会向文件中写入任何内容。

我在这里迷失了一点,甚至不知道你们要导入哪些细节来帮助我弄清楚这一点,但是也许这很重要吗?

  • 工作流核心库基于.NET标准2.0
  • NUnit项目和控制台项目均使用.NET Framework 4.7.2
  • 工作流核心库使用各种Task(例如在Task Parallel Library中)
  • 使用Microsoft.Extensions.DependencyInjection库通过依赖注入构建工作流核心库

这是相关代码: 首先是工作流程类:

public class HelloWorldWorkflow : IWorkflow
{
    public string Id => nameof(HelloWorldWorkflow);
    public int Version => 1;
    public void Build(IWorkflowBuilder<object> builder)
    {
        builder.StartWith((context) =>
        {
            File.WriteAllText(@"C:\Test\test.txt", "Test line worked!");
            return ExecutionResult.Next();
        });
    }
}

来自控制台应用程序的调用代码(正在运行):

class Program
{
    static void Main(string[] args)
    {
        var serviceCollection = new ServiceCollection();
        serviceCollection.AddLogging((config) => config.AddConsole());
        serviceCollection.AddWorkflow();

        serviceCollection.AddTransient<LogStep>();

        var serviceProvider = serviceCollection.BuildServiceProvider();

        var host = serviceProvider.GetService<IWorkflowHost>();
        host.RegisterWorkflow<HelloWorldWorkflow>();

        host.Start();

        host.StartWorkflow(nameof(HelloWorldWorkflow));

        Console.WriteLine("Done");
        Console.ReadLine();

        host.Stop();
    }
}

还有我的测试项目中的代码(不起作用):

[TestFixture]
public class ExplorationTests
{
    private ServiceProvider _serviceProvider;
    private IWorkflowHost _host;

    [OneTimeSetUp]
    public void Init()
    {
        var serviceCollection = new ServiceCollection();
        serviceCollection.AddLogging((config) => config.AddConsole());
        serviceCollection.AddWorkflow();

        serviceCollection.AddTransient<LogStep>();
        serviceCollection.AddTransient<HelloWorldWorkflow>();

        _serviceProvider = serviceCollection.BuildServiceProvider();

        _host = _serviceProvider.GetService<IWorkflowHost>();
        _host.RegisterWorkflow<HelloWorldWorkflow>();

        _host.Start();
    }

    [Test]
    public void Test()
    {
        _host.StartWorkflow(nameof(HelloWorldWorkflow));

    }

    [OneTimeTearDown]
    public void TearDown()
    {
        _host.Stop();
    }
}

我很高兴能找到解决这个问题的线索。

3 个答案:

答案 0 :(得分:1)

工作流的执行是异步的,因此您必须等待某种类型的事件发生,这标志着完成。 否则,您的测试拆除将在工作流有机会做任何事情之前杀死主机。

此答案的第一版包含:

.Wait()的结果中添加StartWorkflow或其过载之一(允许指定最大等待时间)以阻止测试,直到工作流完成。

不幸的是,这是错误的,因为StartWorkflow返回一个Task,仅产生工作流实例的ID。解决此任务后,您的工作流程可能没有做任何有意义的事情。

GitHub上有一个功能请求,要求提供所需功能:Wait for workflow to finish

在该请求得到解决之前,您可以通过创建ManualResetEventAutoResetEvent并将其放在您的最终工作流步骤可以访问并在其上调用.Set()的位置来帮助自己。您的测试应通过在其上调用.WaitOne()来等待它(这是阻塞的)。

另一个可能足够(但效率不高)的事件只是等待了足够长的时间:Thread.Sleep(2000)等待了两秒钟。请注意,即使那样之后,由于工作流执行程序的异步特性,您的工作流可能仍未完成。

答案 1 :(得分:0)

您可以通过将'var serviceCollection'设置为ExplorationTests的类成员来尝试吗?否则代码看起来还可以。

答案 2 :(得分:0)

您的测试似乎开始在主机中运行任务,然后退出而无需等待完成。一次拆卸将立即运行并停止主机。

在不等待任务完成之前,您不应该结束测试。