【问题标题】:Why does this NSubstitute Received Call Fail?为什么这个 NSubstitute Received Call 失败?
【发布时间】:2018-06-24 13:42:32
【问题描述】:

有问题的测试:“TestGetAllPeople()”

我正在尝试使用单元测试框架(因为我没有很多使用它们的经验)并且遇到了一个我无法确定的错误。

根据文档 (https://nsubstitute.github.io/help/received-calls/)(我相信)。它不应该失败,因为我通过调试器运行它并调用了它,它检索了两个人,所以我显然遗漏了一些东西。

  • VS2015,
  • .NET 4.5.2,
  • NSubstitute 3.1,
  • NUnit 3.9 和
  • NUnitAdapter 3.9。

Person.cs

public interface IPersonRepository
{
    List<Person> GetPeople();
    Person GetPersonByID(string ID);
}

public class Person
{
    public string ID;
    public string FirstName;
    public string LastName;

    public Person(string newID, string fn, string ln)
    {
        ID = newID;
        FirstName = fn;
        LastName = ln;
    }
}

public class PersonService
{
    private IPersonRepository personRepo;

    public PersonService(IPersonRepository repo)
    {
        personRepo = repo;
    }

    public List<Person> GetAllPeople()
    {
        return personRepo.GetPeople();
    }

    public List<Person> GetAllPeopleSorted()
    {
        List<Person> people = personRepo.GetPeople();
        people.Sort(delegate (Person lhp, Person rhp)
        {
            return lhp.LastName.CompareTo(rhp.LastName);
        });
        return people;
    }

    public Person GetPerson(string ID)
    {
        try
        {
            return personRepo.GetPersonByID(ID);
        }
        catch(ArgumentException)
        {
            return null; // No person found
        }
    }
}

测试

[TestFixture]
public class Tests
{

    //This is our mock object
    private IPersonRepository personRepoMock;

    //Data
    private Person personOne = new Person("1", "A", "Test");
    private Person personTwo = new Person("2", "B", "Yest");
    private List<Person> peopleList;

    [SetUp]
    public void TestInit()
    {
        //For lauching VS debugger
        //System.Diagnostics.Debugger.Launch();

        peopleList = new List<Person>();
        peopleList.AddRange(new Person[] { personOne, personTwo });

        //Mock/Fake object of IPersonRepository
        personRepoMock = Substitute.For<IPersonRepository>();


        //FAKES --------------------------------------------
        //Remember Subtitute.ForPartsOf!
        //https://nsubstitute.github.io/help/partial-subs/
    }

    [TearDown]
    public void TearDown()
    {
        //TODO
    }

    [Test]
    public void CanCreate()
    {
        Person person = new Person("1", "A", "Test");
        Assert.IsNotNull(person);
    }

    [Test]
    public void TestGetAllPeople()
    {
        //Expects a call to GetPeople and returns peopleList
        //Weirdly enough the call IS receieved as it DOES return the people list
        //Through the mock, but throws saying it wasnt
        personRepoMock.Received().GetPeople().Returns(peopleList);

        //-------------Expectations-------------
        //Checking for multiple received 
        //personRepoMock.Received(x).etc
        //Clearing
        //personRepoMock.ClearReceivedCalls();
        //-------------Expectations-------------

        //Using this version to continue development for now.
        //personRepoMock.GetPeople().Returns(peopleList);
        PersonService pServ = new PersonService(personRepoMock);
        Assert.AreEqual(2, pServ.GetAllPeople().Count);
    }

    [Test]
    public void TestGetAllPeopleSorted()
    {
        //Expectss a call to get people and returns a peopleList
        //personRepoMock.Received().GetPeople().Returns(peopleList);
        personRepoMock.GetPeople().Returns(peopleList);

        PersonService pServ = new PersonService(personRepoMock);

        List<Person> people = pServ.GetAllPeopleSorted();
        Assert.NotNull(people);
        Assert.AreEqual(2, people.Count);
        Person p = people[0];
        Assert.AreEqual("Test", p.LastName);
    }

    [Test]
    public void TestGetSinglePersonWithValidID()
    {
        //Expectss a call to GetPerson and returns personOne
        personRepoMock.GetPersonByID(Arg.Is("1")).Returns(personOne);

        PersonService pServ = new PersonService(personRepoMock);

        Person p = pServ.GetPerson("1");
        Assert.IsNotNull(p);
        Assert.AreEqual(p.ID, "1");
    }

    [Test]
    public void TestGetSinglePersonWithInvalidID()
    {
        //Throwing
        personRepoMock.GetPersonByID(Arg.Any<string>()).Returns(x => 
        {
            throw new ArgumentException();
        });

        PersonService pServ = new PersonService(personRepoMock);
        Assert.IsNull(pServ.GetPerson("-1"));
    }
}

取消注释以进行调试。

//System.Diagnostics.Debugger.Launch();

欢迎对风格/约定提出任何建议(我意识到现在测试名称不是很好)。

我会根据要求更新任何信息。

【问题讨论】:

  • Received 用于断言,当您尝试在测试方法的执行中使用它时。在您调用Received 时,测试中的方法尚未被调用,因此模拟还没有收到任何东西。因此测试失败。

标签: c# visual-studio unit-testing nunit nsubstitute


【解决方案1】:

Received 用于在您尝试在测试方法的执行中使用它时进行断言。在您调用Received 时,测试中的方法尚未被调用,因此模拟尚未收到任何内容。因此测试失败。

考虑以下

[Test]
public void TestGetAllPeople() {
    //Arrange
    var expected = peopleList.Count;
    personRepoMock.GetPeople().Returns(peopleList);
    var subject = new PersonService(personRepoMock);

    //Act
    var actual = subject.GetAllPeople().Count;

    //Assert
    Assert.AreEqual(expected, actual);
    personRepoMock.Received().GetPeople();
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-30
    • 2015-04-21
    • 2011-09-01
    相关资源
    最近更新 更多