假设我有这个代码库(不能更改)
namespace Library.Namespace;
public interface ISomething { }
internal class Something : ISomething {
public Something(...) {
...
}
}
public class Anything {
private Something _Something;
public Anything (ISomething something) {
_Something = (Something) something;
...
}
}
和我想创建模拟的Anything
类:
public MockAnything : Mock<Anything> {
public MockSomething Something { get; }
public MockAnything()
: this(new MockSomething()) {
}
public MockAnything(MockSomething something)
: base(something.Object) {
Something = something;
}
}
public MockSomething : Mock<ISomething> {
}
到目前为止一切都很好(也就是编译器很高兴),但是在运行时调用
时得到异常:var mock = new MockAnything();
var object = mock.Object; // <-- exception here
System.InvalidCastException
Unable to cast object of type 'Castle.Proxies.ISomethingProxy' to type 'Library.Namespace.Something'.
at Library.Namespace.Something..ctor(ISomething something)
at Castle.Proxies.AnythingProxy..ctor(IInterceptor[] , ISomething something)
任何想法如何正确模拟类,在构造函数中使用直接强制转换?
使用Moq时,最好和最简单的方法是基于接口创建mock。不幸的是,您不能更改库并在那里添加接口或摆脱强制转换(无论如何这都是最好的)。
从设计的角度来看,我建议在库代码周围创建一个不能更改的包装器。此外,您还创建了一个接口(我们称之为IAnything
),其中包含您想要使用的方法。您将把IAnthing
注入到代码中,而不是直接在代码中使用Anything
。下面的代码概述了必要的类:
public IInterface IAnything
{
// Members of the original Anything class that you want to use in your code
}
public class AnythingWrapper : IAnything
{
private readonly Anything _anything;
public AnythingWrapper(Anything anything)
{
_anything = anything;
}
// IAnything implementation
}
虽然这看起来有点额外的工作,但它通常是通过粘贴和复制来完成的。此外,您还可以在代码和库代码之间创建一个抽象层。如果库将来更改,您可以在包装器类中应用更改,而无需更改接口。
一旦创建了接口,就可以轻松地创建模拟,例如:
var mockAnything = new Mock<IAnything>();