gpt4 book ai didi

C# 模拟测试 - Moq 列表不能是 'foreach',告诉 'NullReferenceException'

转载 作者:太空宇宙 更新时间:2023-11-03 23:21:53 25 4
gpt4 key购买 nike

环境:NUnit 2.6.4; NUnit 测试适配器 2.0.0;最小起订量 4.2.1; VisualStdio 4.6;

简介:我实现了一个 HomeSecuritySystem,其中有供应商的传感器、警报、电源、显示器的接口(interface)。我想测试它的实现。我想测试“SystemCheckPass”子例程。

我模拟一个 ISensor 列表并构造“SecurityController”,然后运行“SystemCheckPass”子例程。当它执行到“SystemCheckPass”子例程时,“foreach”无法正常运行,它显示“NullReferenceException”。

在 ISensors 的 MockList 上的“foreach”循环的测试函数中一切正常。简单地将 ref 传递给“SecurityController”后,“list”的“foreach”“循环”无法找到其元素的“ref”。我对此很困惑。

谁能告诉我为什么?

安全 Controller 的实现。

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 进行单元测试。系统检查通过的单元测试。

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 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.

最佳答案

这主要是因为GetEnumerator被要求为您的 IList<T> ,你没有 mock 。

我建议不要模拟类似集合的对象,如 IList<T> .只需传递它们的实际实现即可。否则就像你在测试 foreach有效。

关于C# 模拟测试 - Moq 列表不能是 'foreach',告诉 'NullReferenceException',我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35120534/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com