我可以使用 moq Mock<MyClass> 来模拟类,而不是接口吗?

问题描述 投票:0回答:2

浏览https://github.com/Moq/moq4/wiki/Quickstart,我看到它模拟了一个接口。

我的遗留代码中有一个没有接口的类。当我

Mock<MyClass>
时,我得到以下异常:

附加信息:无法实例化类的代理:MyCompnay.Mylegacy.MyClass。

如何使用 Moq 从遗留代码中模拟类?

c# unit-testing moq
2个回答
38
投票

可以模拟具体类

[TestClass]
public class PlaceholderParserFixture
{

  public class Foo
  {
     public virtual int GetValue()
     {
        return 11;
     }
  }

  public class Bar
  {
     private readonly Foo _foo;

     public Bar(Foo foo)
     {
        _foo = foo;
     }

     public int GetValue()
     {
        return _foo.GetValue();
     }
  }

  [TestMethod]
  public void MyTestMethod()
  {
     var foo = new Mock<Foo>();
     foo.Setup(mk => mk.GetValue()).Returns(16);
     var bar = new Bar(foo.Object);

     Assert.AreEqual(16, bar.GetValue());
  }

}

但是,

  • 一定是公开课
  • 要模拟的方法必须是虚拟的

我收到的消息:

使班级内部化

Castle.DynamicProxy.Generators.GeneratorException:类型 MoqFixture+Foo 不是公开的。无法为不可访问的类型创建代理。

或者,有一个非虚拟方法

System.NotSupportedException:非虚拟(可在 VB 中重写)成员上的设置无效:mk => mk.GetValue()

与您的

cannot instantiate
消息不匹配,因此其他内容似乎有问题。

如果模拟对象上没有默认构造函数,您可能会收到该错误消息

例如

public class Foo
{

    private int _value;
    public Foo(int value)
    {
       _value = value;
    }

    public virtual int GetValue()
    {
        return _value;
    }
}

可以通过将值传递到 Mock<> ctor 来解决这个问题

例如

var foo = new Mock<Foo>(MockBehavior.Strict, new object[] { 11 });

0
投票

Moq 无法为大多数具体类(也称为密封类或非虚拟成员)进行模拟。您可以使用库 MockMe 模拟此类类(免责声明:我是作者)。

使用它的 API(希望)非常直观

using MockMe;

var mock = Mock.Me(default(MyRepo)); // rebuild test project after writing this to help IDE fill in IntelliSense

mock.Setup.ExpensiveDatabaseCall().Returns(99);

MyRepo myRepo = mock.MockedObject;
var result = myRepo.ExpensiveDatabaseCall();

Assert.Equal(99, result);
mock.Assert.ExpensiveDatabaseCall().WasCalled();
© www.soinside.com 2019 - 2024. All rights reserved.