Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/asp.net/34.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# System.NullReferenceException-.Net(MVC)模拟单元测试_C#_Asp.net_Asp.net Mvc_Unit Testing_Moq - Fatal编程技术网

C# System.NullReferenceException-.Net(MVC)模拟单元测试

C# System.NullReferenceException-.Net(MVC)模拟单元测试,c#,asp.net,asp.net-mvc,unit-testing,moq,C#,Asp.net,Asp.net Mvc,Unit Testing,Moq,我正在控制器中使用Moq和Nunit框架对我的一个方法进行单元测试。我正在努力理解模拟存储库和其他对象的概念,但没有取得多大成功 我有一种方法不允许用户删除帐户中有未结余额的学生。该方法的逻辑在我的StudentController中,在POST方法中,我还使用了存储库和依赖项注入(不确定这是否导致了问题)。当我运行单元测试时,有时它会转到我的GET Delete()方法,如果它转到POST方法,我会收到一个错误,在代码行中说“Object reference not set to a inst

我正在控制器中使用Moq和Nunit框架对我的一个方法进行单元测试。我正在努力理解模拟存储库和其他对象的概念,但没有取得多大成功

我有一种方法不允许用户删除帐户中有未结余额的学生。该方法的逻辑在我的StudentController中,在POST方法中,我还使用了存储库和依赖项注入(不确定这是否导致了问题)。当我运行单元测试时,有时它会转到我的
GET Delete()
方法,如果它转到
POST方法
,我会收到一个错误,在代码行中说“Object reference not set to a instance of a Object”,如果(s.PaymentDue>0)

学生控制员

 public class StudentController : Controller
    {
        private IStudentRepository studentRepository;

        public StudentController()
        {
            this.studentRepository = new StudentRepository(new SchoolContext());
        }

        public StudentController(IStudentRepository studentRepository)
        {
            this.studentRepository = studentRepository;
        }
        [HttpPost]
        [ValidateAntiForgeryToken]

        public ActionResult Delete(int id)
        {
            //studentRepository.DeleteStudent(id);
            Student s = studentRepository.GetStudentByID(id);
            var paymentDue = false;
            if (s.PaymentDue > 0)
            {
                paymentDue = true;
                ViewBag.ErrorMessage = "Cannot delete student. Student has overdue payment. Need to CLEAR payment before deletion!";
                return View(s);
            }
            if (!paymentDue)
            {
                try
                {
                    Student student = studentRepository.GetStudentByID(id);
                    studentRepository.DeleteStudent(id);
                    studentRepository.Save();
                }
                catch (DataException /* dex */)
                {
                    //Log the error (uncomment dex variable name after DataException and add a line here to write a log.
                    return RedirectToAction("Delete", new { id = id, saveChangesError = true });
                }
            }
            //return View(s);
            return RedirectToAction("Index");
        }
单元测试方法

private int studentID;

        [TestMethod]
        public void StudentDeleteTest()
        {
            //create list of Students to return

            var listOfStudents = new List<Student>();
            listOfStudents.Add(new Student
            {
                LastName = "Abc",
                FirstMidName = "Abcd",
                EnrollmentDate = Convert.ToDateTime("11/23/2010"),
                PaymentDue = 20
            });

            Mock<IStudentRepository> mockStudentRepository = new Mock<IStudentRepository>();
            mockStudentRepository.Setup(x => x.GetStudents()).Returns(listOfStudents);

            var student = new StudentController(mockStudentRepository.Object);

            //Act
            student.Delete(studentID);

            ////Assert
            mockStudentRepository.Verify(x => x.DeleteStudent(studentID), Times.AtLeastOnce());
        }
private int studentID;
[测试方法]
public void StudentDeleteTest()
{
//创建要返回的学生列表
var listOfStudents=新列表();
学生列表。添加(新学生)
{
LastName=“Abc”,
FirstMidName=“Abcd”,
EnrollmentDate=Convert.ToDateTime(“11/23/2010”),
应付账款=20
});
Mock mockStudentRepository=新建Mock();
mockStudentRepository.Setup(x=>x.GetStudents()).Returns(学生列表);
var student=newstudentcontroller(mockStudentRepository.Object);
//表演
student.Delete(studentID);
////断言
mockStudentRepository.Verify(x=>x.deleteStustudent(studentID),Times.atlestOnce());
}

我不知道您的GetStudentByID方法到底在做什么,但它似乎返回null。 查看它的代码,检查它是否调用了您没有模拟的方法,或者返回值是否被很好地检索到


希望这有助于S

我不知道您的GetStudentByID方法到底在做什么,但它似乎返回null。 查看它的代码,检查它是否调用了您没有模拟的方法,或者返回值是否被很好地检索到


希望这有助于S

您没有嘲笑
GetStudentByID
。您只模拟了
GetStudents
(您正在测试的操作方法甚至没有调用它)。调用未模拟的方法时,Moq的默认行为是返回null。因此,当控制器调用
studentRepository.GetStudentByID
时,它返回null。随后,当您尝试访问学生的
PaymentDue
属性时,该属性为null,从而导致
NullReferenceException

有两件事需要解决:模拟方法并启用
MockBehavior.Strict

var mockStudentRepository = new Mock<IStudentRepository>(MockBehaviorStrict);
我还没有检查您的代码的其余部分,以查看您是否没有模拟任何其他内容,但是启用严格的模拟行为将帮助您找到需要模拟的内容

…好的,我检查过了。您还需要模拟存储库的
Save
方法


另一方面,您的控制器正在调用
studentRepository.GetStudentByID(id)
两次。这将导致对您的存储库(可能还有数据库)进行不必要的调用,并降低速度。相反,只需重用已经包含您的学生的
s



另一方面,您似乎没有在控制器中使用依赖项注入框架。我建议你调查一下(我最喜欢的),团结等等。。这将允许您在应用程序中使用单个控制器,并防止控制器需要了解有关
StudentRepository
SchoolContext
的任何信息。它所需要知道的就是
是udentrepository
。退房。

你没有嘲笑过
GetStudentByID
。您只模拟了
GetStudents
(您正在测试的操作方法甚至没有调用它)。调用未模拟的方法时,Moq的默认行为是返回null。因此,当控制器调用
studentRepository.GetStudentByID
时,它返回null。随后,当您尝试访问学生的
PaymentDue
属性时,该属性为null,从而导致
NullReferenceException

有两件事需要解决:模拟方法并启用
MockBehavior.Strict

var mockStudentRepository = new Mock<IStudentRepository>(MockBehaviorStrict);
我还没有检查您的代码的其余部分,以查看您是否没有模拟任何其他内容,但是启用严格的模拟行为将帮助您找到需要模拟的内容

…好的,我检查过了。您还需要模拟存储库的
Save
方法


另一方面,您的控制器正在调用
studentRepository.GetStudentByID(id)
两次。这将导致对您的存储库(可能还有数据库)进行不必要的调用,并降低速度。相反,只需重用已经包含您的学生的
s



另一方面,您似乎没有在控制器中使用依赖项注入框架。我建议你调查一下(我最喜欢的),团结等等。。这将允许您在应用程序中使用单个控制器,并防止控制器需要了解有关
StudentRepository
SchoolContext
的任何信息。它所需要知道的就是
是udentrepository
。退房。

你知道什么是
NullReferenceException
吗?你能调试并找出哪个对象是空的吗?你能调试并告诉我们你在哪一行得到错误吗?@Rinktacular他已经告诉我们错误来自哪一行了。s.PaymentDue是可空类型吗?您必须指定s.PaymentDue.Value吗?您没有模拟
GetStudentByID
。你只模拟了
GetStudents
。你知道什么是
NullReferenceException
吗?你能调试并找出哪个对象是空的吗?你能调试并告诉我们你在哪一行得到错误吗