2

我是使用 nsubstitute 进行测试的新手。所以也许这对你来说是一个微不足道的问题。但我找不到一个。我请你帮我解决以下问题。

我通过测试一个抽象类遇到了一个问题:

public abstract class BaseClass
{
    public string Name
    {
        get { return GetName(); }
        set { SetName(value); }
    }

    protected abstract string GetName();

    protected abstract void SetName(string value);

}

我想测试一下,getter 和 setter 是否在抽象类中被正确调用。要获取我派生的类的受保护抽象方法:

public class MockClass:BaseClass
{
    protected override string GetName()
    {
        return MockGetName();
    }

    protected override void SetName(string value)
    {
        MockSetName(value);
    }

    public virtual string MockGetName()
    {
        return string.Empty;
    }

    public virtual void MockSetName(string value)
    {
    }
}

现在我想测试,如果调用了 MockGetName()-Method,则在通过以下方式获取 Name-Property 的值时:

public void TestNameGetter()
{
    // arrange
    MockClass mock = Substitute.For<MockClass>();
    mock.MockGetName().Returns(" Irgendein Name ");

    // act
    string name = mock.Name;

    // assert
    Assert.AreEqual(" Irgendein Name ", name, "Wrong name");
    mock.DidNotReceive().MockSetName(Arg.Any<string>());
    mock.Received().MockGetName();
}

但是从未调用过 MockGetName 方法,并且变量名称的值错误。

我希望任何人都可以帮助我测试功能。谢谢

4

1 回答 1

2

问题是 NSubstitute 正在拦截MockClass.GetName调用并返回该调用的默认值(空字符串)。因此,当mock.Name在测试中运行时,它会调用GetName并且我们会返回空字符串,而不管MockGetName会返回什么。

我不确定您要实现的确切目标,但是如果您想将 NSubstitute 用于此类事情,首先想到的选择是直接使用该属性,或更改GetName为 public。或者,避免使用 NSubstitute 并将测试所需的逻辑直接放入MockClass.

可模拟属性

    public abstract class BaseClass
    {
        public virtual string Name { get; set; }
    }

    [Test]
    public void TestNameGetter()
    {
        var mock = Substitute.For<BaseClass>();
        mock.Name.Returns("ABC");

        string name = mock.Name;

        Assert.AreEqual("ABC", name, "Wrong name");
    }

公共访问器方法

    public abstract class BaseClass
    {
        public string Name
        {
            get { return GetName(); }
            set { SetName(value); }
        }

        public abstract string GetName();
        public abstract void SetName(string value);
    }

    [Test]
    public void TestNameGetter()
    {
        var mock = Substitute.For<BaseClass>();
        mock.GetName().Returns("ABC");

        string name = mock.Name;

        Assert.AreEqual("ABC", name, "Wrong name");
        mock.DidNotReceive().SetName(Arg.Any<string>());
        mock.Received().GetName();
    }

手工编码的模拟

    public class MockClass : BaseClass
    {
        public bool GetNameWasCalled = false;
        public bool SetNameWasCalled = false;
        protected override string GetName() { GetNameWasCalled = true; return "ABC"; }
        protected override void SetName(string value) { SetNameWasCalled = true; }
    }

    [Test]
    public void TestNameGetter()
    {
        // arrange
        var mock = new MockClass();

        // act
        string name = mock.Name;

        // assert
        Assert.AreEqual("ABC", name, "Wrong name");
        Assert.False(mock.SetNameWasCalled);
        Assert.True(mock.GetNameWasCalled);
    }
于 2014-07-01T23:41:37.030 回答