我正在使用具有模块化行为的C#(基于.NET Core)开发一个聊天机器人。我想要开发的一个行为是" admin" (以及其他功能)应允许管理员按名称动态启用或禁用其他行为的模块。
我希望管理模块通过检查其类型信息并执行以下操作来确定行为的名称:
var name = behaviour.GetType().GetTypeInfo().Name.Replace("Behaviour", string.Empty).ToLowerInvariant();
在BDD规范中我先写作,我试图建立一个"行为链"由管理模块(被测系统)和模拟行为组成。测试涉及发送应该导致管理模块启用或禁用模拟行为的命令。
这是我到目前为止所做的:
public BehaviourIsEnabled() : base("Admin requests that a behaviour is enabled")
{
var mockTypeInfo = new Mock<TypeInfo>();
mockTypeInfo.SetupGet(it => it.Name).Returns("MockBehaviour");
var mockType = new Mock<Type>();
mockType.Setup(it => it.GetTypeInfo()).Returns(mockTypeInfo.Object);
// TODO: make mock behaviour respond to "foo"
var mockBehaviour = new Mock<IMofichanBehaviour>();
mockBehaviour.Setup(b => b.GetType()).Returns(mockType.Object);
this.Given(s => s.Given_Mofichan_is_configured_with_behaviour("administration"), AddBehaviourTemplate)
.Given(s => s.Given_Mofichan_is_configured_with_behaviour(mockBehaviour.Object),
"Given Mofichan is configured with a mock behaviour")
.And(s => s.Given_Mofichan_is_running())
.When(s => s.When_I_request_that_a_behaviour_is_enabled("mock"))
.And(s => s.When_Mofichan_receives_a_message(this.JohnSmithUser, "foo"))
.Then(s => s.Then_the_mock_behaviour_should_have_been_triggered())
.TearDownWith(s => s.TearDown());
}
运行此问题时,GetTypeInfo()
是Type
上的扩展方法,因此Moq会抛出异常:
表达式引用不属于模拟的方法 object:it =&gt; it.GetTypeInfo()
另一种选择,我可以向Name
添加IMofichanBehaviour
属性,但我不想将任意方法/属性添加到仅限生产代码真的有测试代码的好处。
答案 0 :(得分:1)
使用满足被模拟的假类来保持简单。
public class MockBehaviour : IMofichanBehaviour { ... }
然后测试看起来像
public BehaviourIsEnabled() : base("Admin requests that a behaviour is enabled") {
// TODO: make mock behaviour respond to "foo"
var mockBehaviour = new MockBehaviour();
this.Given(s => s.Given_Mofichan_is_configured_with_behaviour("administration"), AddBehaviourTemplate)
.Given(s => s.Given_Mofichan_is_configured_with_behaviour(mockBehaviour),
"Given Mofichan is configured with a mock behaviour")
.And(s => s.Given_Mofichan_is_running())
.When(s => s.When_I_request_that_a_behaviour_is_enabled("mock"))
.And(s => s.When_Mofichan_receives_a_message(this.JohnSmithUser, "foo"))
.Then(s => s.Then_the_mock_behaviour_should_have_been_triggered())
.TearDownWith(s => s.TearDown());
}