我正在写一个测试,它依赖于一个扩展方法的结果,但我不希望该扩展方法将来的失败也会破坏这个测试。模仿这一结果似乎是显而易见的选择,但Moq似乎没有提供一种覆盖静态方法(扩展方法的要求)的方法。Moq.Protected和Moq.Stub也有类似的想法,但它们似乎没有为这种情况提供任何东西。我是不是遗漏了什么,或者我应该以不同的方式来做这件事?
这里有一个简单的例子,它使用通常的"Invalid member on a non-overridable“失败。这是一个需要模拟扩展方法的坏例子,但它应该这样做。
public class SomeType {
int Id { get; set; }
}
var ListMock = new Mock<List<SomeType>>();
ListMock.Expect(l => l.FirstOrDefault(st => st.Id == 5))
.Returns(new SomeType { Id = 5 });
对于任何可能建议我使用隔离器的TypeMock上瘾者,我很欣赏你的努力,因为看起来TypeMock可以蒙住眼睛喝醉了,但我们的预算不会很快增加。
发布于 2009-02-18 18:02:26
扩展方法只是伪装的静态方法。像Moq或Rhinomocks这样的模拟框架只能创建对象的模拟实例,这意味着模拟静态方法是不可能的。
发布于 2014-03-29 02:04:03
如果您可以更改扩展方法代码,则可以像这样编写代码,以便能够进行测试:
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
public static class MyExtensions
{
public static IMyImplementation Implementation = new MyImplementation();
public static string MyMethod(this object obj)
{
return Implementation.MyMethod(obj);
}
}
public interface IMyImplementation
{
string MyMethod(object obj);
}
public class MyImplementation : IMyImplementation
{
public string MyMethod(object obj)
{
return "Hello World!";
}
}
因此,扩展方法只是实现接口的包装器。
(您可以只使用实现类,而不使用扩展方法,扩展方法是一种语法糖。)
您可以模拟implementation接口并将其设置为extensions类的实现。
public class MyClassUsingExtensions
{
public string ReturnStringForObject(object obj)
{
return obj.MyMethod();
}
}
[TestClass]
public class MyTests
{
[TestMethod]
public void MyTest()
{
// Given:
//-------
var mockMyImplementation = new Mock<IMyImplementation>();
MyExtensions.Implementation = mockMyImplementation.Object;
var myClassUsingExtensions = new MyClassUsingExtensions();
// When:
//-------
var myObject = new Object();
myClassUsingExtensions.ReturnStringForObject(myObject);
//Then:
//-------
// This would fail because you cannot test for the extension method
//mockMyImplementation.Verify(m => m.MyMethod());
// This is success because you test for the mocked implementation interface
mockMyImplementation.Verify(m => m.MyMethod(myObject));
}
}
发布于 2010-04-29 04:35:58
https://stackoverflow.com/questions/562129
复制相似问题