创建类的模拟而不调用原始类构造函数



假设我有这个代码库(不能更改)

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>();

最新更新