我有以下界面来模拟:
internal interface IRenderer
{
void Render<T>(StringWriter stringWriter, T item) where T : struct;
void Render(StringWriter stringWriter, decimal item);
void Render(StringWriter stringWriter, string item);
}
测试如下:
[Test]
[TestCase("dummy-string", "dummy-string")]
[TestCase(123, "123")]
[TestCase(123.456, "123.456")]
[TestCase(true, "True")]
[TestCase('C', "C")]
public void RendersExpectedValues(dynamic item, string rendered)
{
// Do some stuff
using (var stringWriter = new StringWriter(renderedBuilder)
{
_mockRenderer.Setup(x => x.Render(textWriter, item));
_renderer.Render(textWriter, item);
}
Assert.It.Worked();
}
正如您所看到的,item
是dynamic
,重载是在运行时确定的......我玩过
Type type = item.GetType();
_mockRenderer.Setup(x => x.Render<type>(textWriter, item));
和
Type type = item.GetType();
_mockRenderer.Setup(x => x.Render<typeof(type)>(textWriter, item));
两者都没有(当然)。
这可能吗?我可以将字符串测试用例删除到单独的测试中。
答案 0 :(得分:1)
我认为这并不是直接的 - 我总是得到:
错误:表达式树可能不包含动态操作`
尝试在安装程序中使用dynamic
时。 AFAIK您需要在每种支持的类型上做明确的Setup()
。
但是,你可以稍微干一点,但是使用通用的设置辅助方法,例如:
static class Helpers
{
public static Mock<IRenderer> Setup<T>(this Mock<IRenderer> mockRenderer) where T : struct
{
mockRenderer.Setup(x => x.Render(It.IsAny<StringWriter>(), It.IsAny<T>()))
.Callback<StringWriter, T>((sw, s) => sw.Write(s));
return mockRenderer;
}
}
然后可以设置+调用:
[Test]
[TestCase("dummy-string", "dummy-string")]
[TestCase(123, "123")]
[TestCase(123.456, "123.456")]
[TestCase(true, "True")]
public void RendersExpectedValuesString(dynamic item, string rendered)
{
var _mockRenderer = new Mock<IRenderer>()
.Setup<double>()
.Setup<bool>()
.Setup<int>()
.Setup<decimal>();
_mockRenderer.Setup(x => x.Render(It.IsAny<StringWriter>(), It.IsAny<string>()))
.Callback<StringWriter, string>((sw, s) => sw.Write(s));
var renderedBuilder = new StringBuilder();
var sut = new SomethingWhichUsesRenderer(_mockRenderer.Object);
// Do some stuff
using (var stringWriter = new StringWriter(renderedBuilder))
{
sut.DoSomething(stringWriter, item);
// This obviously just tests the Mock ...
Assert.AreEqual(renderedBuilder.ToString(), rendered);
// Do actual unit tests + Mock.Verifies here
}
}