【问题标题】:NUnit - Unit test case to test TransactionNUnit - 测试事务的单元测试用例
【发布时间】:2019-11-05 16:38:36
【问题描述】:

我有一个方法如下。

我想为下面的方法写两个测试用例。

1) 提交数据的成功事务

2) 带有回滚数据的失败事务

我如何编写一个涉及事务的测试用例并成功和失败?

public async Task<List<string>> UpdateRequest(MetaData data, List<string> Ids, string requestedBy)
{
    var transaction = await _databaseUtility.CreateTransaction(ConnectionString);

    var messages = new List<string>();

    try
    {
        // Update data
        await _testDal.Update(data, requestedBy, transaction);

        // Update status
        await _sampleDal.UpdateStatus(Ids, requestedBy, transaction);

        // Update saved data
        await _testDal.UpdateSavedData(data, requestedBy, transaction);

        _databaseUtility.CommitTransaction(transaction);
    }
    catch (Exception exception)
    {
        _databaseUtility.RollbackTransaction(transaction);
    }

    return messages;
}

【问题讨论】:

  • 您在哪里将值添加到messages 列表?

标签: c# unit-testing nunit


【解决方案1】:

我认为你有两个问题:

  1. 您在单元测试中使用 async 和 await,这意味着您的代码将在任何事情真正完成之前继续运行。
    您可以阅读此https://johnthiriet.com/removing-async-void/#

    我将解释捕获, 确保await _testDal.Update(data, requestedBy, transaction);Update() 函数返回Task
    然后您可以使用_testDal.Update(data, requestedBy, transaction).Wait() 调用它进行单元测试。
    await 调用您的常规代码。这将使您的测试代码等到更新完成,而常规代码保持原样。

  2. 我会使用像 NSubstitute https://nsubstitute.github.io/ 这样的模拟服务来模拟响应。模拟服务将使用反射来替换实现 _testDal 的接口或类。
    这样,当您调用 Update() 函数时,您可以将某些参数传递给它,并在将这些参数传递给函数时抛出异常。
    并传递另一组参数并为它们返回正确的消息。

如果您希望传递不同的参数,您可以使用 Nunit TestCase(new[] params...) 并将一组不同的参数传递给相同的单元测试。 但是对于 PassTest 和 FailTest,我会使用 2 个或更多不同的测试。

【讨论】:

    【解决方案2】:

    您可以通过使用 NUnit 内置的TestCaseSource 属性和TestCaseData 类来实现它。

    [TestCaseSource(nameof(TestCases))]
    public List<string> TestTransaction(MetaData data, List<string> ids, string requestedBy)
    {
        return testObject.UpdateRequest(data, ids, requestedBy).GetAwaiter().GetResult();
    }
    
    public static IEnumerable TestCases
    {
        get
        {
            //successful
            yield return new TestCaseData(new MetaData(), new List<string> { "1", "2" }, "test").Returns(new List<string> { "test1", "test2" });
            //failed
            yield return new TestCaseData(null, new List<string> { "1", "2" }, "test").Returns(new List<string> { "test1", "test2" });
            //another failed
            yield return new TestCaseData(new MetaData(), new List<string> { "1", "2" }, string.Empty).Returns(new List<string> { "test1", "test2" });
        }
    }
    

    这里有几点

    • 为什么在UpdateRequest 方法中需要List 的消息?它是 仅初始化,不添加值。在上面的代码 sn-p 中,UpdateRequest 方法返回的消息列表与预期结果简单匹配,但您也可以在此处编写任何 Assert
    • 失败的交易取决于你的逻辑,你可以传递一个无效的 导致异常的数据,在代码 sn-p 中我使用了空 MetadatarequestedBy
    • async Task&lt;List&lt;string&gt;&gt;返回结果同步执行到 匹配预期的返回结果List&lt;string&gt;。异步测试用例 来源是NUnit github中的公开提案

    作为一个选项,您还可以为成功和失败的事务编写单独的测试,并异步调用UpdateRequest 方法。

    到目前为止,您尚未共享组件的详细信息,并且很难对 DAL 做出假设,但是如果您想为 Update 方法使用模拟,您可以尝试使用 Moq 库和 @用于响应/返回值的 987654339@ 方法,如 answer 中所述

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-27
      • 2015-01-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多