管理员返回null,但为什么?

Rus*_*ino 2 c# unit-testing moq

我有以下测试.

[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 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);
        }
    }
Run Code Online (Sandbox Code Playgroud)

我很难理解为什么管理员返回NULL.

var administrateur = repository.SelectById(monGuid);
Run Code Online (Sandbox Code Playgroud)

我甚至对存储库进行了计数测试,它有5个项目.

有帮助吗?

Mar*_*son 7

我经常看到这个问题 - 你从根本上误解了嘲讽/伪造/抄袭的目的是什么.也就是说,你正在编写一个虚假实现的测试,因此,测试是没用的.想一想 - 你的测试试图证明什么?您正在尝试验证是否可以从存储库中获取结果,但是:

// 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);
Run Code Online (Sandbox Code Playgroud)

上面的行是从您的存储库中提取数据,但存储库不是真正的实现.这不是生产代码.如果是这样,那么为什么然后断言Administrator从假存储库中取出的对象呢?您正在测试的行为是ID功能搜索,但它是在您的测试夹具中定义的!您已经创建了一个存根/伪实现,然后对其进行了测试 - 仅此而已.Mocks/Stubs/Fakes意味着有预期或提供预制结果来推动真实类型的测试(阅读:生产中使用的类型).测试模拟本身没有任何结果.

在编写任何测试代码之前,您应该问自己这个测试的目的是什么? 如果您无法回答该问题,请在编写测试代码之前解决该问题.如果你真的要测试你的AdministratorRepository,你将实例化存储库的生产代码版本然后操纵它,然后在其行为的某些方面断言.

这篇博文可能对您有所帮助.我主张放弃模拟框架并使用基于状态的测试,直到你完全清楚模拟/存根适合的位置,因为它很容易被基于交互的测试弄糊涂.

*编辑 - 好的,这里(粗略地)你的代码看起来应该是什么 忽略实现细节,只关注每种类型的角色,并注意到它很简单.

// 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)));
    }
}
Run Code Online (Sandbox Code Playgroud)

请注意,我没有使用模拟框架,因为我不需要.生产代码没有任何需要模拟/存根/伪造的有问题的依赖项.