我一直在使用moq设置,我希望得到你的帮助,感谢任何帮助。
public interface IMessageHub
{
void Subscribe<T>(string topic, Action<T> callback);
}
拥有消息中心,您可以在其中订阅主题,如果有消息已发布,则会使用消息调用回调。
每条消息都来自
public class MessageBase { }
例如,我创建了2种消息类型:
public class RefreshMessage : MessageBase { }
public class CancelMessage : MessageBase { }
在代码的某些部分,消息有2个订阅
...
MessageHub.Subscribe<RefreshMessage>("Refresh", RefreshMethod);
MessageHub.Subscribe<CancelMessage>("Cancel", CancelMethod);
...
回调方法是私有的,所以我只能通过单元测试中的设置来获取它们。
private void RefreshMethod(RefreshMessage message) { ... }
private void CancelMethod(CancelMessage message) { ... }
这些部分是由框架提供的,所以我无法改变它们。
在单元测试中,我想用Moq模拟MessageHub,并为每个动作模拟Subscribe方法,并获得调用subscribe方法的回调方法。
通常,我必须为每个消息类型创建2个设置,如下所示:
var messageHubMock = new Mock<IMessageHub>();
var methods = new List<dynamic>();
//setup for RefreshMessage
messageHubMock.Setup(_=>_.Subscribe(It.IsAny<string>,It.IsAny<Action<RefreshMessage>>())
.Callback<string,Action<RefreshMessage>>((s,a)=> methods.Add(a));
//setup for CancelMessage
messageHubMock.Setup(_=>_.Subscribe(It.IsAny<string>,It.IsAny<Action<CancelMessage>>())
.Callback<string,Action<CancelMessage>>((s,a)=> methods.Add(a));
问题是,如何在1个设置中进行2设置?
以下设置不起作用,但显示我尝试过的那些。
messageHubMock.Setup(_=>_.Subscribe(It.IsAny<string>,It.IsAny<Action<object>>())
.Callback<string,Action<object>>((s,a)=> methods.Add(a));
messageHubMock.Setup(_=>_.Subscribe(It.IsAny<string>,It.IsAny<Action<dynamic>>())
.Callback<string,Action<dynamic>>((s,a)=> methods.Add(a));
messageHubMock.Setup(_=>_.Subscribe(It.IsAny<string>,It.IsAny<object>())
.Callback<string,object>((s,a)=> methods.Add(a));
//does not compile
messageHubMock.Setup(_=>_.Subscribe(It.IsAny<string>,It.IsAny<Action>())
.Callback<string,Action>((s,a)=> methods.Add(a));
messageHubMock.Setup(_=>_.Subscribe(It.IsAny<string>,It.IsAny<Action<MessageBase>>())
.Callback<string,Action<MessageBase>>((s,a)=> methods.Add(a));
所有这些都不适合表达式,所以即使在代码中调用了subscibre,Moq也不会在设置上运行Callback,因为subscribe是用“不同”参数调用的。
我想我需要在此创建自己的表达式过滤器逻辑。 你能帮助我,如何创建这个设置,只有1个设置?
答案 0 :(得分:0)
有时,Moq始终是这项工作的最佳工具。请尝试使用简单的存根。我仍然在寻找一种在Moq中实现它的方法,但现在应该可以使用。
[TestClass]
public class UnitTest {
[TestMethod]
public void _Mock_Action_T_Without_Moq() {
//Arrange
var callbacks = new Dictionary<string, dynamic>();
var messageHubMock = new MessageHubStub(callbacks);
//Act
var sut = new Sut(messageHubMock.Object);
//Assert
Assert.IsTrue(callbacks.Count == 2);
Assert.IsNotNull(callbacks["Refresh"]);
Assert.IsNotNull(callbacks["Cancel"]);
}
public class Sut {
public Sut(IMessageHub MessageHub) {
MessageHub.Subscribe<RefreshMessage>("Refresh", RefreshMethod);
MessageHub.Subscribe<CancelMessage>("Cancel", CancelMethod);
}
private void CancelMethod(CancelMessage obj) {
throw new NotImplementedException();
}
private void RefreshMethod(RefreshMessage obj) {
throw new NotImplementedException();
}
}
public class MessageHubStub : IMessageHub {
private Dictionary<string, dynamic> callbacks;
public MessageHubStub(Dictionary<string, dynamic> callbacks) {
this.callbacks = callbacks;
}
public IMessageHub Object { get { return this; } }
public void Subscribe<T>(string topic, Action<T> callback) {
callbacks.Add(topic, callback);
}
}
public interface IMessageHub {
void Subscribe<T>(string topic, Action<T> callback);
}
public class MessageBase { }
public class RefreshMessage : MessageBase { }
public class CancelMessage : MessageBase { }
}
此外,如果每条消息都来自MessageBase
,请考虑将其作为集线器的约束
public interface IMessageHub {
void Subscribe<T>(string topic, Action<T> callback) where T : MessageBase;
}