环境:NUnit 2.6.4; NUnit TestAdapter 2.0.0; Moq 4.2.1; VisualStdio 4.6;
简介: 我实现了一个HomeSecuritySystem,其中包含供应商的传感器,报警器,PowerSuply,显示器接口。我想测试它的实现。我想测试一下SystemCheckPass'子程序。
我模拟了一个ISensor列表并构建了' SecurityController'然后我运行了SystemCheckPass'子程序。当它执行到SystemCheckPass'子程序,' foreach'没有正确运行,它说'NullReferenceException'。
对于“foreach”的测试功能来说,这一切都很好。循环在ISensors的MockList上。只需将参考文献传递给' SecurityController',就可以了解' foreach' '环路' ' list'无法找到' 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和Moq来进行UnitTest。系统检查通行证的单元测试。
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);
}
}
}
NUnit Test Framework提供的错误:
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.
答案 0 :(得分:3)
这主要是因为你GetEnumerator
调用了IList<T>
,你没有模仿。
我建议不要模拟像IList<T>
这样的类似集合的对象。只需传递它们的实际实现。否则,就像你正在测试foreach
的工作原理。