【问题标题】:How to create Mock for the abstract base class using MOQ framework?如何使用 MOQ 框架为抽象基类创建 Mock?
【发布时间】:2011-05-23 18:01:15
【问题描述】:

我想为 MyClass 编写单元测试,但它的基类是一个抽象类。

public class MyClass : AbstractBaseClass
{
}

我想模拟 AbstractBase 类,以便在创建要测试的 MyClass 实例时跳过其构造函数中的一些逻辑。无论如何我可以做到这一点吗?

//Unit Test
var test = new Mock<IInterface>();
var derivedclass = new DerivedClass(test.Object);

test.Setup(d=>d.MyMethod(It.IsAny<string>()).returns(2);
derivedclass.MyMethod("hello");


// Derived Class
class DerivedClass : AbstractClass{

     //constuctor
    public DerivedClass(IInterface interface){
        _interface = interface;
    }
    public MyMethod(string str){
        return 2;
    }
}

//Abstract Class
public abstract class AbstractClass
{

 // This method gets called when i create the  instance of the derived class in my unit   
  test..

   protected AbstractedClass() : this(new SomeOtherClass()){
       DoSomethingElse();    /// I want to skip this method or mock it.
   }
 }

【问题讨论】:

  • 您遇到了设计问题。 AbstractClass 是其 ctor 中依赖项的硬编码实例化。如果您要模拟此依赖项上的方法,则需要更改 AbstractClass ctor 以接收依赖项。如果你能详细说明这个方法在内部做了什么,也许你会得到一些更好的答案

标签: unit-testing moq


【解决方案1】:

通过从基类继承,您正在扩展它。更多的是让您的代码进入可测试状态,而不是让 Moq 为您工作。

  1. 您可以使用组合而不是基类,然后使用可以模拟的依赖注入(通过接口)。
  2. 或者如果你必须继承然后提取你不想运行到另一个类的逻辑,你通过依赖注入再次注入。
  3. 或者让你不想运行的逻辑成为你可以模拟的虚拟方法的一部分。 (就像@Ohad Horesh 的回答:)

    public virtual void DoSomethingElse();
    
    mock.Setup(abs => abs.Foo());  //here the mocked method will be called  
                                   // rather than the real one
    

如果这些选项不可行,那么您要么必须通过派生类测试该功能,要么使用其他模拟框架,例如 TypeMock Isolator、Moles 或 JustMock。

【讨论】:

    【解决方案2】:

    是的,这是 Moq 中非常基本的场景。
    假设您的抽象类如下所示:

    public class MyClass : AbstractBaseClass
    {
        public override int Foo()
        {
            return 1;
        }
    }
    

    你可以写下面的测试:

    [Test]
    public void MoqTest()
    {
        var mock = new Moq.Mock<AbstractBaseClass>();            
        // set the behavior of mocked methods
        mock.Setup(abs => abs.Foo()).Returns(5);
    
        // getting an instance of the class
        var abstractBaseClass = mock.Object;
        // Asseting it actually works :)
        Assert.AreEqual(5, abstractBaseClass.Foo());
    }
    

    【讨论】:

    • 不,我认为我没有正确解释它...实际上我不想对 Abstract 类本身进行单元测试..
    • 请注意 Foo() 必须在 AbstractBaseClass 的定义中标记为虚拟
    • 在这种情况下,你真的不需要测试任何东西。您只需将模拟值与 const 值进行比较。这样做是没有意义的。
    猜你喜欢
    • 2020-04-04
    • 1970-01-01
    • 2012-03-03
    • 2014-01-02
    • 1970-01-01
    • 1970-01-01
    • 2014-06-15
    • 2014-10-02
    • 2012-05-11
    相关资源
    最近更新 更多