2016-01-31 44 views
1

環境:NUnit的2.6.4; NUnit TestAdapter 2.0.0; Moq 4.2.1; VisualStudio 4.6;C#模擬測試 - 起訂量清單不可能 '的foreach' 告訴 '的NullReferenceException'

簡介: 我implemet在具有供應商的傳感器,報警,PowerSuply,顯示器的接口HomeSecuritySystem。我想測試它的實現。我想測試'SystemCheckPass'子例程。

我嘲笑的iSensor的列表,並構建「SecurityController」,然後我跑「SystemCheckPass」子程序。當它執行到'SystemCheckPass'子例程時,'foreach'不能正常運行,它說'NullReferenceException'。

它是在對ISensors的MockList了「的foreach」循環測試功能都很好。在簡單地將ref傳遞給'SecurityController'之後,'list'的'foreach''loop'找不到它的元素的'ref'。我對此很困惑。

有人能告訴我爲什麼嗎?

實施安全控制器。

using System; 
using System.Collections.Generic; 
using HomeSecuritySystem.Sensors; 
using HomeSecuritySystem.Comms; 
using HomeSecuritySystem.Power; 
using HomeSecuritySystem.Display; 
using HomeSecuritySystem.Alarm; 
using HomeSecuritySystem.Report; 

using System.Threading; 
using System.Diagnostics; 

namespace HomeSecuritySystem 
{ 
    public class SecurityController : ControllerBase 
    { 
     public int Value; 

     public ICollection<ISensor> sensors; 
     public IComms comms; 
     public IPowerSupply powerSupply; 
     public IAlarm alarm; 
     public IDisplay display; 

     public SecurityController(ICollection<ISensor> sensors, IComms comms, IPowerSupply powerSupply, IAlarm alarm, IDisplay display) 
      : base(sensors, comms, powerSupply, alarm, display) 
     { 
      this.sensors = sensors; 
      this.comms = comms; 
      this.powerSupply = powerSupply; 
      this.alarm = alarm; 
      this.display = display; 

      // bind the power down event when system initials, because it never changes. 
      powerSupply.OnNoPower += new Events.NoPowerEvent(PowerSupplyNoPower); 

      // initialize 
      IsArmedLastSate = IsArmed; 
      IsStayLastSate = IsStay; 
     } 

     public bool SystemCheckPass() 
     { 
      // <---- begin system check 
      bool systemCheckPass = true; 

      // check the device power except sensors 
      if (alarm.IsOn == false || comms.IsOn == false || powerSupply.IsOn == false) 
      { 
       // part of system check, power is off, system check fail 
       systemCheckPass = false; 
      } 




      // check power of sensors 
      foreach (ISensor sensor in sensors) 
      { 
       if (sensor.IsOn == false) 
        systemCheckPass = false; 
      } 
      /* 
      // check the battery of sensors 
      foreach (ISensor sensor in sensors) 
      { 
       switch (sensor.Type) 
       { 
        // part of system check, motion sensor's battery is low, system check fail 
        case Report.SensorType.Motion: 
         IMotionSensor motionSensor = (IMotionSensor)(sensor); 
         if (motionSensor.IsLowBattery == true) 
         { 
          systemCheckPass = false; 
         } 
         break; 

        // part of system check, smoke sensor's battery is low, system check fail 
        case Report.SensorType.Smoke: 
         ISmokeSensor smokeSensor = (ISmokeSensor)(sensor); 
         if (smokeSensor.IsLowBattery == true) 
         { 
          systemCheckPass = false; 
         } 
         break; 

        default: 
         // so far, only two kinds of sensors 
         throw new Exception("no exit sensor type!"); 
       } 

      } 

      //check the battery of power supply 
      if (powerSupply.IsLowBattery) 
      { 
       systemCheckPass = false; 
      } 

      */ 
      // system check over ----> 
      return systemCheckPass; 
     } 

     public override void SystemCheck() 
     { 
      // <---- begin system check 
      bool systemCheckPass = true; 
      List<int> lowBatterySensorIDList = new List<int>(); 

      // check the device power except sensors 
      if (alarm.IsOn == false || comms.IsOn == false || powerSupply.IsOn == false) 
      { 
       // part of system check, power is off, system check fail 
       systemCheckPass = false; 
      } 

      // check power of sensors 
      foreach (ISensor sensor in sensors) 
      { 
       if (sensor.IsOn == false) 
        systemCheckPass = false; 
      } 

      bool lowBatterySensorExist = false; 
      // check the battery of sensors 
      foreach (ISensor sensor in sensors) 
      { 
       switch (sensor.Type) 
       { 
        // part of system check, motion sensor's battery is low, system check fail 
        case Report.SensorType.Motion: 
         IMotionSensor motionSensor = (IMotionSensor)(sensor); 
         if (motionSensor.IsLowBattery == true) 
         { 
          lowBatterySensorIDList.Add(motionSensor.Id); 
          systemCheckPass = false; 
          lowBatterySensorExist = true; 
         } 
         break; 

        // part of system check, smoke sensor's battery is low, system check fail 
        case Report.SensorType.Smoke: 
         ISmokeSensor smokeSensor = (ISmokeSensor)(sensor); 
         if (smokeSensor.IsLowBattery == true) 
         { 
          lowBatterySensorIDList.Add(smokeSensor.Id); 
          systemCheckPass = false; 
          lowBatterySensorExist = true; 
         } 
         break; 

        default: 
         // so far, only two kinds of sensors 
         throw new Exception("no exit sensor type!"); 
       } 

      } 

      //check the battery of power supply 
      bool BatteryOfPowSupplyIsLow = false; 
      if (powerSupply.IsLowBattery) 
      { 
       systemCheckPass = false; 
       BatteryOfPowSupplyIsLow = true; 
      } 
      // system check over ----> 

      // <---- report begin 
      if (systemCheckPass) 
      { 
       display.ShowSystemReady(); 
      } 
      else 
      { 
       display.ShowSystemNotReady(); 
      } 

      if (lowBatterySensorExist) 
      { 
       display.ShowSensorLowBattery(lowBatterySensorIDList); 
      } 
      if (BatteryOfPowSupplyIsLow) 
      { 
       display.ShowPowerSupplyLowBattery(); 
      } 
      // report end ---> 
     } 

     public override void ClearMemory() 
     { 
      display.ClearSentReport(); 
      display.ClearAlarmSound(); 
      display.ClearSystemArmed(); 
      foreach (ISensor sensor in sensors) 
      { 
       display.ClearSensorDetected(sensor.Id); 
      } 
     } 

     // bind to event sensor.OnDetectionStateChanged 
     public void ArmSensorDetected(ISensor sensor) 
     { 
      if (sensor.Detected) 
      { 
       alarm.SoundAlarm(); 
       display.ShowAlarmSound(); 
       display.ShowSensorDetected(sensor.Id); 

       Report.Report report = new Report.Report(); 
       report.SensorId = sensor.Id; 
       report.SensorType = sensor.Type; 
       report.Time = new DateTime(); 
       report.Type = Report.ReportType.Intrusion; 

       display.ShowSentReport("sensor detected"); 
       comms.InformSecurity("sensor detected"); 
      } 
     } 

     public void ArmStaySensorDetected(ISensor sensor) 
     { 
      if (sensor.Type == Report.SensorType.Motion) 
      { 
       IMotionSensor motionSensor = (IMotionSensor)(sensor); 
       if (motionSensor.Detected && motionSensor.IsPerimeterSensor) 
       { 
        alarm.SoundAlarm(); 
        display.ShowAlarmSound(); 
        display.ShowSensorDetected(sensor.Id); 
        display.ShowSentReport("sensor detected"); 
        comms.InformSecurity("sensor detected"); 
       } 
      } 
     } 

     public void SmokeSensorDetected(ISensor sensor) 
     { 
      if (sensor.Type == Report.SensorType.Smoke) 
      { 
       ISmokeSensor smokeSensor = (ISmokeSensor)(sensor); 
       if (smokeSensor.Detected) 
       { 
        Report.Report report = new Report.Report(); 
        report.SensorId = sensor.Id; 
        report.SensorType = sensor.Type; 
        report.Time = new DateTime(); 
        report.Type = Report.ReportType.Smoke; 

        alarm.SoundAlarm(); 
        display.ShowAlarmSound(); 
        display.ShowSensorDetected(sensor.Id); 
        display.ShowSentReport("sensor detected"); 
        comms.InformSecurity("sensor detected"); 
       } 
      } 
     } 

     public void PowerSupplyNoPower() 
     { 
      Report.Report report = new Report.Report(); 
      report.Time = new DateTime(); 
      report.Type = Report.ReportType.NoPower; 

      comms.InformSecurity("power down"); 
      display.ShowSentReport("power down"); 
     } 

     private bool IsArmedLastSate; 
     private bool IsStayLastSate; 

     private void DelegateHandling() 
     { 
      foreach (ISensor sensor in sensors) 
      { 
       sensor.OnDetectionStateChanged += new Events.SensorDetectionStateChangeEvent(ArmSensorDetected); 
      } 

      if (IsArmed == true && IsStay == false) 
      { 
       foreach (ISensor sensor in sensors) 
       { 
        sensor.OnDetectionStateChanged += new Events.SensorDetectionStateChangeEvent(ArmSensorDetected); 
       } 
      } 
      else if (IsArmed == true && IsStay == true) 
      { 
       foreach (ISensor sensor in sensors) 
       { 
        sensor.OnDetectionStateChanged += new Events.SensorDetectionStateChangeEvent(ArmStaySensorDetected); 
       } 
      } 
      else if (IsArmed == false && IsStay == false) 
      { 
       alarm.StopAlarm(); 
      } 

      foreach (ISensor sensor in sensors) 
      { 
       sensor.OnDetectionStateChanged += new Events.SensorDetectionStateChangeEvent(SmokeSensorDetected); 
      } 
     } 

     public void Run() 
     { 
      // initial delegete bind 
      DelegateHandling(); 

      //delegate sensor 
      for (;;) 
      { 
       Thread.Sleep(100); 
       SystemCheck(); 

       if (IsArmedLastSate != IsArmed || IsStayLastSate != IsStay) 
       { 
        // when Security Controller change mode, rebind all sensors' delegete. 
        DelegateHandling(); 

        IsArmedLastSate = IsArmed; 
        IsStayLastSate = IsStay; 
       } 
      } 
     } 

     static int Main(string[] args) 
     { 
      //... 
      return 0; 
     } 
    } 
} 

我使用NUnit和最小起訂量繼續處理的單元測試。系統檢查通行證的單元測試。通過NUnit測試框架給出

using HomeSecuritySystem.Alarm; 
using HomeSecuritySystem.Sensors; 
using Moq; 
using System.Collections.Generic; 

namespace HomeSecuritySystem 
{ 
    using Comms; 
    using Display; 
    using NUnit.Framework; 
    using Power; 
    [TestFixture] 
    public class SecurityControllerTest 
    { 
     [Test] 
     public void Test_System_Check() 
     { 
      //arrange 
      Mock<IMotionSensor> mockMotionSensor = new Mock<IMotionSensor>(); 
      mockMotionSensor.SetupGet(t => t.IsLowBattery).Returns(true); 

      //mock sensors 
      Mock<List<ISensor>> mockSensors = new Mock<List<ISensor>>(); 
      mockSensors.Object.Add(mockMotionSensor.Object); 

      foreach (ISensor sensor in mockSensors.Object) 
      { 
       if (sensor.IsOn == false) 
        ; 
      } 

      Mock<IComms> mockComms = new Mock<IComms>(); 
      mockComms.SetupGet(t => t.IsOn).Returns(true); 
      Mock<IPowerSupply> mockPowerSupply = new Mock<IPowerSupply>(); 
      mockPowerSupply.SetupGet(t => t.IsOn).Returns(true); 
      Mock<IAlarm> mockAlarm = new Mock<IAlarm>(); 
      mockAlarm.SetupGet(t => t.IsOn).Returns(true); 
      Mock<IDisplay> mockDisplay = new Mock<IDisplay>(); 
      SecurityController securityController = new SecurityController(mockSensors.Object, mockComms.Object, mockPowerSupply.Object, mockAlarm.Object, mockDisplay.Object); 

      //act 
      Assert.AreEqual(securityController.SystemCheckPass(), true); 
     } 
    } 
} 

錯誤:

Test Name: Test_System_Check 
Test FullName: HomeSecuritySystem.SecurityControllerTest.Test_System_Check 
Test Source: C:\Users\OEM\Documents\Visual Studio 2015\Projects\HomeSecurityController\HomeSecurityController.UnitTest\SecurityControllerTest.cs : line 17 
    Test Outcome: Failed 
    Test Duration: 0:00:00.569 

Result StackTrace: 
at HomeSecuritySystem.SecurityController.SystemCheckPass() in C:\Users\OEM\Documents\Visual Studio 2015\Projects\HomeSecurityController\HomeSecurityController\SecurityController.cs:line 58 
at HomeSecuritySystem.SecurityControllerTest.Test_System_Check() in C:\Users\OEM\Documents\Visual Studio 2015\Projects\HomeSecurityController\HomeSecurityController.UnitTest\SecurityControllerTest.cs:line 42 
Result Message: System.NullReferenceException : Object reference not set to an instance of an object. 
+1

我只是你使用Visual Studio 4.6 ... –

+0

@PatrickQuirk 「印象深刻」 –

回答

3

這主要是因爲GetEnumerator叫你IList<T>,你沒有嘲笑。

我建議不要嘲笑集合類對象,如IList<T>。只需傳遞它們的實際實現。否則就像你正在測試foreach的作品。

+1

是印象深刻。我將我的測試代碼更改爲 'List Sensors = new List (); Sensors.Add(mockMotionSensor.Object);' 然後它正常工作。謝謝。 – cdhit