开发者

Administrator is returning null but why?

I have the following test.

[TestFixture]
    public class AdministratorRepositoryTests
    {
        private IAdministrateurRepository repository;

        public static IAdministrateurRepository MockAdministrateurRepository(params Administrateur[] items)
        {
            var mockRepos = new Mock<IAdministrateurRepository>();
            mockRepos.Setup(x => x.Select()).Returns(items.AsQueryable());
            return (IAdministrateurRepository)mockRepos.Object;
        }

        [SetUp]
        public void SetupContext()
        {
            Guid gId1 = new开发者_JAVA技巧 Guid("a05fd3de-9ae4-4b0b-b560-fd96678d3019");
            Administrateur a1 = new Administrateur(gId1);

            Guid gId2 = new Guid("e0724d12-d856-4677-89aa-d12611c15a4c");
            Administrateur a2 = new Administrateur(gId2);

            Guid gId3 = new Guid("30a69d49-84e5-42fc-a643-9e42c1350aa8");
            Administrateur a3 = new Administrateur(gId3);

            Guid gId4 = new Guid("b6444711-baee-4da6-87a8-a839c438bdff");
            Administrateur a4 = new Administrateur(gId4);

            Guid gId5 = new Guid("9d805acd-9d59-44ac-892c-438b189bbf94");
            Administrateur a5 = new Administrateur(gId5);

            repository = MockAdministrateurRepository(a1, a2, a3, a4, a5);

        }

        [Test]
        public void peut_recuperer_un_administrateur_dun_repository_par_son_id()
        {
            Guid monGuid = new Guid("a05fd3de-9ae4-4b0b-b560-fd96678d3019");

            var administrateur = repository.SelectById(monGuid);

            administrateur.ShouldNotBeNull();
            administrateur.Id.ShouldEqual(monGuid);
        }
    }

I am struggle to understand WHY the administrateur is returning NULL.

var administrateur = repository.SelectById(monGuid);

I even did a count test on the repository and it has 5 items.

Any help ?


I see this problem a lot -- you're fundamentally misunderstanding what the purpose of mocking/faking/stubbing is. That is, you're writing a test for a fake implementation and, as a result, the test is useless. Think about it -- what is your test trying to prove? You're trying to verify that you can get results out of a repository, but:

// this is a mock/fake/stub/whatever, it's NOT the real class
var repository = new Mock<IAdministrateurRepository>(); 

// and so.. what is the point in this when your 
// IAministratorRepository is not the production version?
var administrateur = repository.SelectById(monGuid);

// The repository is meant to be the focus of the test, 
// yet you're not testing a result of using a real class
administrateur.ShouldNotBeNull();
administrateur.Id.ShouldEqual(monGuid);

The above line is pulling data out of your repository, but the repository is not a real implementation. It's not production code. If so, then why do you then assert on the Administrator object that is pulled out of the fake repository? The behaviour you're testing is the search by ID functionality, yet it is defined inside your test fixture! You've created a stubbed/fake implementation and then tested it -- nothing more. Mocks/Stubs/Fakes are meant to have expectations or provide canned results to drive the testing of real types (read: types used in production). Testing the mock itself achieves nothing.

Before you write any test code, you should ask yourself what is the purpose of this test? If you can't answer that question, resolve it before you write the test code. If you were to actually be testing your AdministratorRepository, you would instantiate the production code version of the repository and then manipulate it, then assert on some aspect of its behaviour.

This blog post might help you. I would advocate ditching mocking frameworks and using state-based testing until you are totally clear on where mocking/stubbing fits in, as it's easy to become confused by interaction-based testing.

*edit -- OK, here's (roughly) what your code should look like Ignore the implementation details, just focus on the roles of each type and notice that it's simple as can be.

// interface
public interface IAdministratorRepository
{
    Administrator SelectById(Guid _id);
    void Add(Administrator _admin);
}

// minimal implementation of admin.  
public class Administrator
{
    public Guid Id { get; set; }

    public Administrator(Guid _id)
    {
        Id = _id;
    }
}

/// <summary>
/// For argument's sakes, this is the class under test.  
/// It's not a mock/fake/stub/whatever; it's the real deal!
/// </summary>
public class RealAdministratorRepository : IAdministratorRepository
{
    private Dictionary<Guid, Administrator> m_items = new Dictionary<Guid, Administrator>();

    public Administrator SelectById(Guid _id)
    {
        // no error handling here; keeping it simple
        if(m_items.ContainsKey(_id))
            return m_items[_id];

        return null;
    }

    public void Add(Administrator _admin)
    {
        // No error handling for brevity's sakes
        m_items.Add(_admin.Id, _admin);
    }
}

// now, here's a very, very simple happy path test for SelectById using
// the real implementation of AdministratorRepository
[TestFixture]
public class AdministratorRepositoryTests
{
    private const string AdminId = "a05fd3de-9ae4-4b0b-b560-fd96678d3019";
    private IAdministratorRepository m_repository;

    [SetUp]
    public void PerTestSetUp()
    {
        // no mocks/stubs required.  m_repository is a RealAdministratorRepository
        // because that's our production class and that's what we want to test!
        m_repository = new RealAdministratorRepository();
        m_repository.Add(new Administrator(new Guid(AdminId)));
    }

    [Test]
    public void SelectById_WithItemsInRepository_ReturnsCorrectItems()
    {
        // ignore the fact that I'm repeating the same string 3 times; brevity again
        var item = m_repository.SelectById(new Guid(AdminId));

        Assert.That(item, Is.Not.Null);
        Assert.That(item.Id, Is.EqualTo(new Guid(AdminId)));
    }
}

Notice that I am not using a mocking framework because I don't need to. The production code doesn't have any problematic dependencies that require mocking/stubbing/faking.


Mocking and faking are two different concepts. You seem to think that you're setting up a repository by adding data to it and expecting that data to be there. That's how a fake repository works; it's like the real repository but much simpler and contains only the data you set it up with. A mock repository on the other hand doesn't actually contain the data, but contains a set of responses to method calls with particular signatures. You set up a response to the Select() call with no parameters, but you're actually invoking the SelectById() call with a particular parameter. Because there's no response set up for this call beforehand, it returns a null result, i.e., the default when no matching call can be found.


You set up Select but uses SelectById in the test.


You have to setup the mock repository in your MockAdministrateurRepository method to return the desired Administarateur.

mockRepos
    .Setup(x => x.SelectById(new Guid("a05fd3de-9ae4-4b0b-b560-fd96678d3019")))
    .Returns(a1);
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜