【问题标题】:Unit Test Value单元测试值
【发布时间】:2013-10-18 16:24:30
【问题描述】:

我正在尝试对这段代码进行单元测试,

public bool IsCityAvailable(Appointment appointment)
{
    var city = _customerRepository.Find(appointment.CustomerId).City;
    return _employeeRepository.Get.Count(x => x.City == city) > 0;
 }

这是我的测试,

    [SetUp]
    public void Setup()
    {
        MockAppointmentRepository = new Mock<IRepository<Appointment>>();
        MockCustomerRepository = new Mock<IRepository<Customer>>();
        MockShiftRepository = new Mock<IRepository<Shift>>();
        MockEmployeeRepository = new Mock<IRepository<Employee>>();

        AppointmentService = new AppointmentService(MockCustomerRepository.Object, MockAppointmentRepository.Object, MockShiftRepository.Object, MockEmployeeRepository.Object);

        Customer = new Customer()
        {
            Address = "88 Taraview Road NE",
            City = "Calgary",
            Email = "charles.norris@outlook.com",
            FirstName = "Charles",
            LastName = "Norris",
            Id = 1,
            Phone = "587-888-8882",
            PostalCode = "X1X 1X1",
            Province = "AB"
        };

        Employee1 = new Employee()
        {
            Address = "12 Saddletowne Road NW",
            City = "Calgary",
            Email = "johnny.bravo@outlook.com",
            FirstName = "John",
            LastName = "Bravo",
            Id = 2,
            Phone = "403-999-2222",
            PostalCode = "X1X 1X1",
            Province = "AB"
        };

        Employee2 = new Employee()
        {
            Address = "12 Saddletowne Road NW",
            City = "Calgary",
            Email = "johnny.bravo@outlook.com",
            FirstName = "John",
            LastName = "Bravo",
            Id = 2,
            Phone = "403-999-2222",
            PostalCode = "X1X 1X1",
            Province = "AB"
        };

        Appointment = new Appointment()
        {
            Id = 1,
            Customer = Customer,
            CustomerId = Customer.Id,
            Employee = Employee1,
            EmployeeId = Employee1.Id,
            ScheduledTime = new DateTime(2013,10,15,18,30,00)
        };
    }

[Test]
public void IsCityAvailableShouldReturnAvailableWhenEmployeeInSameCityFound()
{
    // ARRANGE
    var employees = new List<Employee> { Employee1, Employee2 };

    var result = new Mock<IQueryable<Employee>>();
    result.Setup(r => r.GetEnumerator()).Returns(employees.GetEnumerator());

    MockCustomerRepository.Setup(x => x.Find(It.IsAny<int>())).Returns(Customer);
    MockEmployeeRepository.Setup(x => x.Get).Returns(result.Object);

    // ACT
    AppointmentService.IsCityAvailable(Appointment);

    // ASSERT
    MockCustomerRepository.Verify(x => x.Find(It.IsAny<int>()), Times.Once);
    MockEmployeeRepository.Verify(x => x.Get, Times.Once);
}

我已经调试并单步执行找不到它所指的值 null,我的城市变量是正确的,约会参数已完全填充。有没有我没看到的东西?

这是单元测试的输出错误:

System.ArgumentNullException:值不能为空。参数名称: 论据

这里是堆栈跟踪:

System.ArgumentNullException : Value cannot be null.
Parameter name: arguments
   at System.Linq.Expressions.Expression.RequiresCanRead(Expression expression, String paramName)
   at System.Linq.Expressions.Expression.ValidateOneArgument(MethodBase method, ExpressionType nodeKind, Expression arg, ParameterInfo pi)
   at System.Linq.Expressions.Expression.ValidateArgumentTypes(MethodBase method, ExpressionType nodeKind, ref ReadOnlyCollection`1 arguments)
   at System.Linq.Expressions.Expression.Call(Expression instance, MethodInfo method, IEnumerable`1 arguments)
   at System.Linq.Queryable.Count(IQueryable`1 source, Expression`1 predicate)
   at Zenwire.Services.AppointmentService.IsCityAvailable(Appointment appointment) in AppointmentService.cs: line 81
   at Tests.Unit.Zenwire.Services.AppointmentServiceTests.IsCityAvailableShouldReturnAvailableWhenEmployeeInSameCityFound() in AppointmentServiceTests.cs: line 100

【问题讨论】:

  • _employeeRepository 为空吗?有些东西会是空的。你只需要更加努力地寻找。实际上,我们都可以为您猜测,但无法调试代码,它可能是任何东西。
  • 看起来像 // ACT AppointmentService.IsCityAvailable(Appointment); “约会”为空
  • 当我单步执行时,会填充约会。我认为问题出在模拟设置上?
  • 需要注意的一点是,虽然您的实际方法看起来很干净,但您违反了“最少知识原则”或“得墨忒耳定律”。有些人也将其称为点点滴滴,一般来说,您希望避免这样做。 “最少知识原则”说只与你的直接朋友交谈。在您的第一行应用程序代码中,您调用:_customerRepository.Find(appointment.CustomerId).City 可能没有更好的方法,但这意味着您必须连接一些东西才能使该行代码工作。随着时间的推移,这可能会使测试和维护变得困难。
  • 您采用的方法在这种情况下可能最有意义。这里的替代方法是将客户传递给方法,您的调用代码可能永远不需要访问该方法。所以,它可能已经尽可能干净了,它更像是为未来做准备,因为这可能会导致非常困难的测试场景。

标签: c# unit-testing asp.net-mvc-4 moq


【解决方案1】:

测试是否正确调用了所有内容:

[SetUp]
public void Setup()
{
    MockAppointmentRepository = new Mock<IRepository<Appointment>>();
    MockCustomerRepository = new Mock<IRepository<Customer>>();
    MockShiftRepository = new Mock<IRepository<Shift>>();
    MockEmployeeRepository = new Mock<IRepository<Employee>>();

    AppointmentService = new AppointmentService(MockCustomerRepository.Object, MockAppointmentRepository.Object, MockShiftRepository.Object, MockEmployeeRepository.Object);

    Customer = new Customer()
    {
        Address = "88 Taraview Road NE",
        City = "Calgary",
        Email = "charles.norris@outlook.com",
        FirstName = "Charles",
        LastName = "Norris",
        Id = 1,
        Phone = "587-888-8882",
        PostalCode = "X1X 1X1",
        Province = "AB"
    };

    Employee1 = new Employee()
    {
        Address = "12 Saddletowne Road NW",
        City = "Calgary",
        Email = "johnny.bravo@outlook.com",
        FirstName = "John",
        LastName = "Bravo",
        Id = 2,
        Phone = "403-999-2222",
        PostalCode = "X1X 1X1",
        Province = "AB"
    };

    Employee2 = new Employee()
    {
        Address = "12 Saddletowne Road NW",
        City = "Calgary",
        Email = "johnny.bravo@outlook.com",
        FirstName = "John",
        LastName = "Bravo",
        Id = 2,
        Phone = "403-999-2222",
        PostalCode = "X1X 1X1",
        Province = "AB"
    };

    Appointment = new Appointment()
    {
        Id = 1,
        Customer = Customer,
        CustomerId = Customer.Id,
        Employee = Employee1,
        EmployeeId = Employee1.Id,
        ScheduledTime = new DateTime(2013,10,15,18,30,00)
    };
}

[Test]
public void IsCityAvailableShouldReturnAvailableWhenEmployeeInSameCityFound()
{
// ARRANGE
MockCustomerRepository.Setup(x => x.Find(It.IsAny<int>())).Returns(Customer);
MockEmployeeRepository.Setup(x => x.Get).Returns(new List<Employee> { Employee1, Employee2 }.AsQueryable());

// ACT
AppointmentService.IsCityAvailable(Appointment);

// ASSERT
MockCustomerRepository.Verify(x => x.Find(It.IsAny<int>()), Times.Once);
MockEmployeeRepository.Verify(x => x.Get, Times.Once);
}

测试返回值:

[Test]
public void IsCityAvailableShouldReturnAvailableWhenEmployeeInSameCityFound()
{
// ARRANGE
MockCustomerRepository.Setup(x => x.Find(It.IsAny<int>())).Returns(Customer);
MockEmployeeRepository.Setup(x => x.Get).Returns(new List<Employee> { Employee1, Employee2 }.AsQueryable());

// ACT
var actual = AppointmentService.IsCityAvailable(Appointment);

// ASSERT
Assert.IsTrue(actual);
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-11-03
    • 2016-08-19
    • 2016-05-09
    • 1970-01-01
    • 2017-01-13
    • 1970-01-01
    • 2017-04-25
    相关资源
    最近更新 更多