为什么这个NSubstitute收到呼叫失败?

时间:2018-01-15 22:00:15

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

有问题的测试:" 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();

欢迎任何关于风格/惯例的建议(我认为测试名称现在不是很好)。

我会更新所需的任何信息。

1 个答案:

答案 0 :(得分:2)

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