在单元测试的开关案例中的特定情况下,如何仅调用一个函数?
How to call a function only, when in a specific case in a switch case for unit test?
所以我有一个 class 可以有 4 个状态的门控
public enum DoorControlState
{
DoorClosed,
DoorOpening,
DoorOpen,
DoorBreached
}
要打开门,需要一个访问代码,然后验证该代码,如果正确则打开门。如果门不处于关闭状态,则不会发生任何事情。它应该像这样 RequestEntry(id)[Doorcontrol]->ValidateEntryRequest(id)[IUserValidation]->OK[Doorcontrol]->Open[IDoor]->将状态更改为 DoorOpening。然后Idoor调用DoorOpen,状态变为DoorOpen等。
我已经实现了 DoorControl class 如下
public class DoorControl
{
private IDoor _door;
private IEntryNotification _entryNotification;
private IUserValidation _userValidation;
private DoorControlState _doorControlState;
private int _id;
public DoorControl(IDoor door, IEntryNotification entryNotification, IUserValidation userValidation, DoorControlState doorControlState)
{
_door = door;
_entryNotification = entryNotification;
_userValidation = userValidation;
_doorControlState = doorControlState;
}
public void Run()
{
switch (_doorControlState)
{
case DoorControlState.DoorClosed:
bool foo = RequestEntryId();
if (foo)
{
_door.Open();
_doorControlState = DoorControlState.DoorOpening;
}
break;
case DoorControlState.DoorOpening:
_door.Close();
_doorControlState = DoorControlState.DoorOpen;
break;
case DoorControlState.DoorOpen:
// Do stuff....
break;
case DoorControlState.DoorBreached:
// Do stuff
break;
default:
throw new InvalidEnumArgumentException();
}
}
private bool RequestEntryId()
{
bool maybeFoo = _userValidation.ValidateEnetryRequest();
if (maybeFoo = true)
{
return true;
}
return false;
}
public void DoorOpened()
{
//
}
public void DoorClosed()
{
//
}
}
}
UserValidation 和 Door classes 实现为接口
public interface IUserValidation
{
bool ValidateEnetryRequest();
}
public interface IDoor
{
void Open();
void Close();
}
我正在使用 Nunit 和 NSubstitute 测试我的代码
namespace DoorControl.Unit.Test
{
[TestFixture]
public class DoorControlUnitTest
{
private DoorControl _uut;
private IDoor _door;
private IEntryNotification _entryNotification;
private IUserValidation _userValidation;
private DoorControlState _doorControlState;
[SetUp]
public void SetUp()
{
_door = Substitute.For<IDoor>();
_entryNotification = Substitute.For<IEntryNotification>();
_userValidation = Substitute.For<IUserValidation>();
_doorControlState = DoorControlState.DoorClosed;
_uut = new DoorControl(_door, _entryNotification, _userValidation, _doorControlState);
}
[Test]
public void InputCorrectId()
{
_userValidation.ValidateEnetryRequest().Returns(true);
_uut.RequestEntryId(); // Can't called that cause it's private
_door.Received().Open();
}
}
}
我不知道如何让它只在它处于关门状态时调用 RequestEntryId,而在它处于其他状态时忽略它。
编辑:Doorcontrol 所处的状态应该对其他人隐藏。
public void InputCorrectId()
{
_userValidation.ValidateEnetryRequest().Returns(true);
if(_doorControlState == DoorControlState.DoorClosed){
_uut.RequestEntryId(); // Make it public
}
_door.Received().Open();
}
或者进门控class喜欢:
case DoorControlState.DoorClosed:
RequestEntryId();
我不确定你到底在问什么:你说 "I can't figure out how to make it call RequestEntryId only when it's in the Doorclosed state and ignore it if it's in another state." 是指单元测试吗?我不明白你为什么要那样做。请提供更多信息,如果我能提供帮助,我会更新此答案。
不过,我确实注意到了一些可能对您有所帮助的事情。首先RequestEntryId
有问题:
private bool RequestEntryId()
{
bool maybeFoo = _userValidation.ValidateEnetryRequest();
if (maybeFoo = true)
{
return true;
}
return false;
}
这里maybeFoo = true
是一个覆盖ValidateEntryRequest()
结果的赋值。我认为你打算与 ==
进行比较,但整个方法可以简化为:
private bool RequestEntryId()
{
return _userValidation.ValidateEnetryRequest();
}
有了这个修复,我们可以 运行 一些测试来检查 public Run
方法的行为。鉴于您的 SetUp
创建的门控已经处于 Closed
状态,我们可以测试门是否为有效用户打开,而不为无效用户打开。
[Test]
public void ClosedDoorOpensWhenUserIsValid()
{
_userValidation.ValidateEnetryRequest().Returns(true);
_uut.Run();
_door.Received().Open();
}
[Test]
public void ClosedDoorDoesNotOpenWhenUserInvalid()
{
_userValidation.ValidateEnetryRequest().Returns(false);
_uut.Run();
_door.DidNotReceive().Open();
}
我们还可以检查是否对已打开的门重复验证:
[Test]
public void OpenDoorDoesNotRevalidate()
{
_userValidation.ValidateEnetryRequest().Returns(true);
_uut.Run();
_userValidation.ClearReceivedCalls();
_uut.Run();
_userValidation.DidNotReceive().ValidateEnetryRequest();
}
希望这能给您一些测试的想法。
所以我有一个 class 可以有 4 个状态的门控
public enum DoorControlState
{
DoorClosed,
DoorOpening,
DoorOpen,
DoorBreached
}
要打开门,需要一个访问代码,然后验证该代码,如果正确则打开门。如果门不处于关闭状态,则不会发生任何事情。它应该像这样 RequestEntry(id)[Doorcontrol]->ValidateEntryRequest(id)[IUserValidation]->OK[Doorcontrol]->Open[IDoor]->将状态更改为 DoorOpening。然后Idoor调用DoorOpen,状态变为DoorOpen等。
我已经实现了 DoorControl class 如下
public class DoorControl
{
private IDoor _door;
private IEntryNotification _entryNotification;
private IUserValidation _userValidation;
private DoorControlState _doorControlState;
private int _id;
public DoorControl(IDoor door, IEntryNotification entryNotification, IUserValidation userValidation, DoorControlState doorControlState)
{
_door = door;
_entryNotification = entryNotification;
_userValidation = userValidation;
_doorControlState = doorControlState;
}
public void Run()
{
switch (_doorControlState)
{
case DoorControlState.DoorClosed:
bool foo = RequestEntryId();
if (foo)
{
_door.Open();
_doorControlState = DoorControlState.DoorOpening;
}
break;
case DoorControlState.DoorOpening:
_door.Close();
_doorControlState = DoorControlState.DoorOpen;
break;
case DoorControlState.DoorOpen:
// Do stuff....
break;
case DoorControlState.DoorBreached:
// Do stuff
break;
default:
throw new InvalidEnumArgumentException();
}
}
private bool RequestEntryId()
{
bool maybeFoo = _userValidation.ValidateEnetryRequest();
if (maybeFoo = true)
{
return true;
}
return false;
}
public void DoorOpened()
{
//
}
public void DoorClosed()
{
//
}
}
}
UserValidation 和 Door classes 实现为接口
public interface IUserValidation
{
bool ValidateEnetryRequest();
}
public interface IDoor
{
void Open();
void Close();
}
我正在使用 Nunit 和 NSubstitute 测试我的代码
namespace DoorControl.Unit.Test
{
[TestFixture]
public class DoorControlUnitTest
{
private DoorControl _uut;
private IDoor _door;
private IEntryNotification _entryNotification;
private IUserValidation _userValidation;
private DoorControlState _doorControlState;
[SetUp]
public void SetUp()
{
_door = Substitute.For<IDoor>();
_entryNotification = Substitute.For<IEntryNotification>();
_userValidation = Substitute.For<IUserValidation>();
_doorControlState = DoorControlState.DoorClosed;
_uut = new DoorControl(_door, _entryNotification, _userValidation, _doorControlState);
}
[Test]
public void InputCorrectId()
{
_userValidation.ValidateEnetryRequest().Returns(true);
_uut.RequestEntryId(); // Can't called that cause it's private
_door.Received().Open();
}
}
}
我不知道如何让它只在它处于关门状态时调用 RequestEntryId,而在它处于其他状态时忽略它。
编辑:Doorcontrol 所处的状态应该对其他人隐藏。
public void InputCorrectId()
{
_userValidation.ValidateEnetryRequest().Returns(true);
if(_doorControlState == DoorControlState.DoorClosed){
_uut.RequestEntryId(); // Make it public
}
_door.Received().Open();
}
或者进门控class喜欢:
case DoorControlState.DoorClosed:
RequestEntryId();
我不确定你到底在问什么:你说 "I can't figure out how to make it call RequestEntryId only when it's in the Doorclosed state and ignore it if it's in another state." 是指单元测试吗?我不明白你为什么要那样做。请提供更多信息,如果我能提供帮助,我会更新此答案。
不过,我确实注意到了一些可能对您有所帮助的事情。首先RequestEntryId
有问题:
private bool RequestEntryId()
{
bool maybeFoo = _userValidation.ValidateEnetryRequest();
if (maybeFoo = true)
{
return true;
}
return false;
}
这里maybeFoo = true
是一个覆盖ValidateEntryRequest()
结果的赋值。我认为你打算与 ==
进行比较,但整个方法可以简化为:
private bool RequestEntryId()
{
return _userValidation.ValidateEnetryRequest();
}
有了这个修复,我们可以 运行 一些测试来检查 public Run
方法的行为。鉴于您的 SetUp
创建的门控已经处于 Closed
状态,我们可以测试门是否为有效用户打开,而不为无效用户打开。
[Test]
public void ClosedDoorOpensWhenUserIsValid()
{
_userValidation.ValidateEnetryRequest().Returns(true);
_uut.Run();
_door.Received().Open();
}
[Test]
public void ClosedDoorDoesNotOpenWhenUserInvalid()
{
_userValidation.ValidateEnetryRequest().Returns(false);
_uut.Run();
_door.DidNotReceive().Open();
}
我们还可以检查是否对已打开的门重复验证:
[Test]
public void OpenDoorDoesNotRevalidate()
{
_userValidation.ValidateEnetryRequest().Returns(true);
_uut.Run();
_userValidation.ClearReceivedCalls();
_uut.Run();
_userValidation.DidNotReceive().ValidateEnetryRequest();
}
希望这能给您一些测试的想法。