【问题标题】:How to mock An Abstract Base Class如何模拟一个抽象基类
【发布时间】:2013-12-15 04:19:21
【问题描述】:

我有一个名为“Question”的基类和几个子类,例如“TrueFalse”、“MultipleChoice”、“MatchPairs”等......

基类具有所有子类都使用的逻辑方法,例如发送分数和引发事件。

我已经为子类设置了单元测试,但我不确定如何为基类中的方法设置单元测试。

我做了一些搜索,我知道我需要创建该类的 Mock,但我不确定如何执行此操作,因为我只看到了如何在可实例化的对象上执行此操作。

我在项目中安装了 Moq 和 NUnit,所以理想情况下我喜欢使用它。我还是编程新手,这是我第一次添加单元测试,所以我很感激你能给我的任何建议。

我首先在网站上进行了搜索,发现了几个类似的问题,但他们没有给出任何关于如何做到这一点的示例,只是需要对其进行模拟。

非常感谢。

【问题讨论】:

  • 有一个扩展它的测试虚拟类...?
  • 所以你基本上需要知道如何模拟一个抽象类。就是这样 - 谷歌,你应该找到你需要的(我会帮助你,但我从来没有使用过起订量)
  • @cHao 是的,这很有道理。所以我只是创建一个虚拟子类并将所有内容直接传递给基础。当您考虑它时很明显,其他文章让我感到困惑,似乎人们建议使用 Moq 框架来实例化抽象基类的实例,而我不知道如何做到这一点。我将在我的测试项目中创建一个虚拟类,而不使用 Moq。
  • @AdamRackis 是的,我用谷歌搜索了它,发现人们在谈论它,但没有代码示例
  • 否 - 使用 moq 创建抽象基类的模拟。而已。这就是模拟框架的用途

标签: c# nunit moq


【解决方案1】:

this answer 看来,您需要的是这些方面的东西:

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

【讨论】:

  • 谢谢亚当。这是我需要的,我不知道为什么我搜索时找不到这个,谢谢。
  • 我无法正常工作。我收到错误“方法不公开”。我使用var mock = new Mock&lt;Question&gt;(new object[]{"question text",true}); var Question = mock.Object; Question.Ask(); mock.Verify(m =&gt; m.Ask()); 方法是公开的,但我认为问题是类是抽象的。
  • @guerr - 我不认为这就是你设置模拟的方式。我会以与代码相同的方式创建它,然后使用 Setup 或 moq 为您提供的任何其他方式设置您的模拟值
  • 如果我使用 setup 来定义方法返回的内容,那么我是在测试方法内部的逻辑吗?当我测试一个使用另一个类的类并且我想伪造它返回的行为时,这不是吗?对不起,菜鸟问题,我读了很多书,但这是我第一次真正解决这个问题。我非常感谢您的帮助
  • 我用我使用的代码和我收到的消息提出了一个新问题,所以它更清楚 - stackoverflow.com/questions/20591869/…
【解决方案2】:

我试图模拟一个抽象类,但这种方式对我不起作用。 起作用的是创建一个扩展抽象类的新类

class newclass : abstractClass
{
}

这样我可以设置属性并测试主方法

【讨论】:

    【解决方案3】:

    没有简单的方法来测试它,

    最好的选择是:

    • 将基类方法标记为虚拟
    • 为每个“TrueFalse”、“MultipleChoice”、“MatchPairs”类创建测试类,并覆盖虚拟方法并调用公共抽象方法。

    例如你有下一个继承结构

    class Question {
         protected virtual bool CheckCorrect(params int[] answers){
              return answers.Any(x => x== 42);
         }
    }
    
    class TrueFalse: Question {
         
         public int SelectedAnswer {get;set;}
         public bool IsCorrect(){
              return CheckCorrect(SelectedAnswer );
         }
    }
    class MultipleChoice: Question {
         public int[] SelectedAnswers {get;set;}
         public bool IsCorrect(){
              return CheckCorrect(SelectedAnswers );
         }
    }
    

    测试方法:

    abstract class TrueFalseTest: TrueFalseTest{
    
         public abstract bool CheckCorrectReal(params int[] answers);
         
         public override bool CheckCorrect(params int[] answers){
              return CheckCorrect(SelectedAnswer );
         }
    }
    
    abstract  class MultipleChoiceTest: MultipleChoice {
         public abstract bool CheckCorrectReal(params int[] answers);
         
         public override bool CheckCorrect(params int[] answers){
              return CheckCorrect(SelectedAnswer );
         }
    }
    

    以及测试方法本身:

    class TestQuestionForms{
        [Fact]
        public void TrueFalseTest_ShouldExecute_CheckCorrectReal()
        {
            //setup
            var mock = new Mock<TrueFalseTest>();
    
            mock.Setup(q => q.CheckCorrectReal(It.IsAny<int[] answers>))
                .Returns(true);
    
            //action
            mock.Object.IsCorrect();
           
           //assert
           mock.Verify(db => db.CheckCorrectReal());
    
        }
        [Fact]
        public void MultipleChoiceTest_ShouldExecute_CheckCorrectReal()
        {   
            //setup
            var mock = new Mock<MultipleChoiceTest>();
    
            mock.Setup(q => q.CheckCorrectReal(It.IsAny<int[] answers>))
                .Returns(true);
    
            //action
            mock.Object.IsCorrect();
           
           //assert
           mock.Verify(db => db.CheckCorrectReal());
    
        }
    }
    

    【讨论】:

    • 在 MultipleChoiceTest 抽象类中没有在测试中执行时覆盖 CheckCorrect 的目的是什么。我在这里错过了什么吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-19
    • 2023-03-15
    • 1970-01-01
    • 1970-01-01
    • 2016-12-05
    相关资源
    最近更新 更多