如何使用It.IsIn(someRange)为多个字段迭代POCO属性的组合?

时间:2016-01-06 17:55:27

标签: c# unit-testing nunit moq

我有一个POCO课程:

public class SomeEntity {
  public int Id { get; set; }
  public string FirstName { get; set; }
  public string LastName { get; set; }
}

我想在SomeEntity类中使用不同的值测试其他一些类。问题是我需要测试许多属性的不同组合。例如:

  1. Id = 1,FirstName = null,LastName =“Doe”
  2. Id = 1,FirstName =“”,LastName =“Doe”
  3. Id = 1,FirstName =“John”,LastName =“Doe”
  4. Id = 1,FirstName = null,LastName =“”
  5. 所以在每个测试中我想创建这样的测试对象:

    // test that someOtherObject always return the same result 
    // for testObject with ID = 1 and accepts any values from range of 
    // values for FirstName and LastName
    
    var testObject = new SomeEntity {
      Id = 1, // this must be always 1 for this test
      FirstName = It.IsIn(someListOfPossibleValues), // each of this values must be accepted in test
      LastName = It.IsIn(someListOfPossibleValues) // each of this values must be accepted in test
    }
    
    var result = someOtherObject.DoSomething(testObject);
    
    Assert.AreEqual("some expectation", result);
    

    我不想使用nunit TestCase,因为会有很多组合(巨大的矩阵)。

    我尝试在调试中运行此测试,它只使用list中的第一个值调用DoSomething一次。

    问题:如何查看所有可能值的组合?

2 个答案:

答案 0 :(得分:3)

您错误地使用了It.IsIn;它仅用于在matching arguments时使用,即在Verify调用以检查值是否在一组可能值中,或在Setup调用中用于控制Moq如何响应。 旨在用于以某种方式生成一组测试数据。这正是NUnit的ValuesAttributeValueSourceAttribute所针对的。

关于你因为组合太多而使用NUnit的反对意见,那是因为你不想写所有的组合,或者因为你不想要那么多的测试?如果它是前者,则使用NUnit的属性和CombinatorialAttribute使NUnit完成创建所有可能测试的工作。像这样:

[Test]
[Combinatorial]
public void YourTest(
    [Values(null, "", "John")] string firstName, 
    [Values(null, "", "Doe")] string lastName)
{
    var testObject = new SomeEntity {
        Id = 1, // this must be always 1 for this test
        FirstName = firstName,
        LastName = lastName
    };

    var result = someOtherObject.DoSomething(testObject);

    Assert.AreEqual("some expectation", result);
}

该测试将运行9次(2个参数中的每一个的3个数据,因此3 * 3)。请注意,组合是默认值。

但是如果你只反对你的结果中的测试数量,那么请专注于你真正想要测试的内容并编写那些测试,而不是用每个可能的值进行游戏。

答案 1 :(得分:0)

因为FirstName和LastName中的每一个都在列表中,所以看起来最简单的就是做2个循环

foreach (var fname in firstNamePossibleValues) {
    foreach (var lname in lastNamePossibleValues) {
        var testObject = new SomeEntity {
           Id = 1, // this must be always 1 for this test
           FirstName = fname, // each of this values must be accepted in test
           LastName = lname // each of this values must be accepted in test
        }

        var result = someOtherObject.DoSomething(testObject);
        Assert.AreEqual("some expectation", result);
    }
}