【问题标题】:Unit Test NService.Send from an API Controller来自 API 控制器的单元测试 NService.Send
【发布时间】:2016-08-17 19:04:43
【问题描述】:

我有一个使用 NServiceBus 发布命令的 API 控制器。我正在使用 NUnit 和 NSubstitute 进行测试。我想测试命令中是否填充了模型中的某些属性

这是我的带有路由的控制器。

[RoutePrefix("api/fileService")]
public class FileServiceController : ApiController
{
    [HttpPost]
    [Route("releasefile")]
    public async Task<IHttpActionResult> ReleaseFile(FileReleaseAPIModels.ReleaseFileModel model)
    {
        var currentUser = RequestContext.Principal?.Identity as ClaimsIdentity;


        if (model.FileType.Equals("ProductFile"))
        {
            _logger.Info($"Releasing Product files for date: {model.FileDate.ToShortDateString()} ");
            _bus.Send<IReleaseProductFiles>("FileManager.Service", t =>
            {
                t.FileId = Guid.NewGuid();
                t.RequestedDataDate = model.FileDate;
                t.RequestingUser = currentUser?.Name;
                t.RequestDateTime = DateTime.Now;
            });
        }
        return Ok();
    }

}

在我的测试中,我替换(模拟)Ibus 并尝试验证收到的呼叫。下面是测试方法:

    [Test]
    public async Task TestReleaseProductsFile()
    {
        var bus = Substitute.For<IBus>();
        var dbContent = _container.Resolve<IFileManagerDbContext>();
        var apiContext = new FileServiceController(bus, dbContent);

        //Create a snapshot
        var releaseDate = DateTime.Now.Date;
        var result = await apiContext.ReleaseFile(new ReleaseFileModel
        {
            FileDate = releaseDate,
            FileType = "ProductFile"
        });

        Assert.That(result, Is.Not.Null, "Result is null");

        Assert.That(result, Is.TypeOf<OkResult>(), "Status code is not ok");

        bus.Received(1)
            .Send<IReleaseProductFiles>(Arg.Is<string>("FileManager.Service"), Arg.Is<Action<IReleaseProductFiles>>(
                action =>
                {
                    action.FileId = Guid.NewGuid();
                    action.RequestedDataDate = releaseDate;
                    action.RequestingUser = String.Empty;
                    action.RequestDateTime = DateTime.Now;
                }));
    }

这会导致错误 - 即使消息已实际发送。这是错误消息:

NSubstitute.Exceptions.ReceivedCallsException : Expected to receive exactly 1 call matching:
    Send<IReleaseProductFiles>("Capelogic.Service", Action<IReleaseProductFiles>)
Actually received no matching calls.
Received 1 non-matching call (non-matching arguments indicated with '*' characters):
    Send<IReleaseProductFiles>("Capelogic.Service", *Action<IReleaseProductFiles>*)

我显然在这里遗漏了一些明显的东西。

【问题讨论】:

    标签: unit-testing nservicebus nsubstitute


    【解决方案1】:

    这里的问题在于SendAction&lt;IReleaseProductFiles&gt; 参数——我们无法自动判断两个不同的操作是否相同。相反,NSubstitute 依赖于等效的引用。因为测试和生产代码都创建了自己的 Action 实例,所以它们总是不同的,NSubstitute 会说调用不匹配。

    有一个few different options for testing this。这些示例与Expression&lt;Func&lt;&gt;&gt; 相关,但同样的想法也适用于Action&lt;&gt;s。

    在这种情况下,我很想间接测试一下:

    [Test]
    public async Task TestReleaseProductsFile()
    {
        var bus = Substitute.For<IBus>();
        var returnedProductFiles = Substitute.For<IReleaseProductFiles>();
    
        // Whenever bus.Send is called with "FileManager.Service" arg, invoke
        // the given callback with the `returnedProductFiles` object.
        // We can then make sure the action updates that object as expected.
        bus.Send<IReleaseProductFiles>(
                "FileManager.Service",
                Arg.Invoke<IReleaseProductFiles>(returnedProductFiles));
    
        // ... remainder of test ...
    
        Assert.That(result, Is.TypeOf<OkResult>(), "Status code is not ok");
        Assert.That(returnedProductFiles.FileId, Is.Not.EqualTo(Guid.Empty));
        Assert.That(returnedProductFiles.RequestedDataDate, Is.EqualTo(releaseDate));
        Assert.That(returnedProductFiles.RequestingUser, Is.EqualTo(String.Empty));
    }
    

    我建议您查看前面提到的答案,看看是否有更适合您的情况。

    【讨论】:

    • 完美。我只需要进行一项修改 - 而不是:Arg.Invoke>(returnedProductFiles));更改为:Arg.Invoke(returnedProductFiles));
    猜你喜欢
    • 2019-04-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-02
    相关资源
    最近更新 更多