c#mock返回基本方法

时间:2018-01-02 07:41:52

标签: c# unit-testing nunit moq

我正在用NUnit框架编写一个单元测试用例来测试我们的代码。

代码引用了第三方库,如下所示:

class MyClass: BaseClass
{
    public void override FunctionA()
    {
      var a = BaseFunctionB();
    }
}

我们没有BaseClass的源代码,但BaseFunctionB是非虚拟的。

我试图

Setup(x=> x.BaseFunctionB()).Reteruns("my values");

但它不允许。

我只想测试FunctionA中的MyClass,我不在乎BasefunctionB中是否正确。

在这种情况下如何测试?

---------------------------- 2018-01-03更新------------- -------------------- 我对BaseClass

进行了一些更新
public abstract class BaseClass1//we dont have source code for this class
{
    public int GetValue()
    {
        //do something here
        return 1;//
    }

    public abstract int GenerateOutPut();
}


class abstract class BaseClass2: BaseClass1
{
    public new virtual int GetValue()
    {
        return base.GetValue();
    }
}

class MyClass1: BaseClass2
{
    public override int GenerateOutPut()
    {
        var a = GetValue();
        a += 1;
        return a;
    }
}

class MyClass2: BaseClass2
{
    public override int GenerateOutPut()
    {
        var a = GetValue();
        a -= 1;
        return a;
    }
}

// there are many MyClass
class MyClassN: BaseClass2
{
    public override int GenerateOutPut()
    {
        var a = GetValue();
        //different logic here.
        return a;
    }
}

我做了一个用于测试MyClass1的课程,如下所示:

class TestClass1: MyClass1
{
    public override int GetValue()
    {
        return 100;
    }
}

测试用例如下:

public void TestFunction()
{
    var test = new TestClass1();
    var result = test.GetValue();

    assert.AreEqual(101, result);
}

现在我必须创建许多看起来不太好的TestClas。但在运行代码覆盖方面,我必须做到(我尝试使用模拟对象执行,报告中没有代码覆盖,我猜因为它创建代理并在代理上运行它,所以我创建相同的东西我自己来测试原始源代码)

我有更好的解决方案吗?

1 个答案:

答案 0 :(得分:1)

创建第二个基类和新成员以封装第三方依赖项是一个好主意。它允许您覆盖派生类中的成员。一般来说,尽量避免嘲笑你不拥有的东西。而是将第三方依赖项封装在您控制的抽象背后,以便您可以灵活地模拟/存根/伪造任何所需的测试行为。

使用示例中的MyClass1

public class MyClass1 : BaseClass2 {
    public override int GenerateOutPut() {
        var a = GetValue();
        a += 1;
        return a;
    }
}

可以进行以下测试以验证受试者的预期行为。注意Moq允许通过在模拟对象上设置CallBase = true来调用基本成员。

[TestClass]
public class MyClass1_Test {
    [TestMethod]
    public void MyClass1_Should_Generate_Output() {
        //Arrange
        var expected = 0;
        var mock = new Mock<MyClass1>() {
            CallBase = true //<-- let mock call base members
        };
        mock.Setup(_ => _.GetValue()).Returns(expected); // <-- mocked behavior

        var sut = mock.Object; //<-- subject under test.

        //Act
        var actual = sut.GenerateOutPut();

        //Assert
        actual.Should().Be(expected + 1);
    }
}

这几乎就像你手动但现在通过模拟代理一样。