4

我在测试具有 ref 参数的方法时遇到问题。我不是库/代码所有者,所以我无法更改它,所以请不要建议我删除 ref 参数。

我使用这个网站作为参考: http ://ayende.com/wiki/Rhino%20Mocks%203.5.ashx#OutandRefarguments

这是测试:

    [Test]
    public void TestBuildSimpleProfile()
    {
        // arrange
        var barMock = MockRepository.GenerateStrictMock<ICommandBar>();
        var controlBuilder = new ControlBuilder(barMock);

        var user = new Usuario();
        user.PRF_PERFIS = new Perfis();

        var perfil = new Perfil();
        perfil.FNC_FUNCIONALIDADES = new Funcionalidades();
        var func1 = new Funcionalidade();
        func1.FNC_NU_ID = 1;
        func1.FNC_FL_ATIVO = true;
        func1.FNC_NO_CHAVE = "Associar Registros";
        func1.FNC_DE_FUNCIONALIDADE = "{0653aeac-c5ef-46fa-9e99-408719296ed3}";

        perfil.FNC_FUNCIONALIDADES.Add(func1);
        user.PRF_PERFIS.Add(perfil);

        var funcs = new List<IFunctionality>();
        funcs.Add(new FunctionalityAttribute(1,"Associar Registros", "{0653aeac-c5ef-46fa-9e99-408719296ed3}", "SGIGT", true,"admin,editor"));

        var uid = new UIDClass() { Value = "{0653aeac-c5ef-46fa-9e99-408719296ed3}" };
        var arg = Arg<object>.Ref(Is.Anything(), 0).Dummy;

        // act
        controlBuilder.Build(user, funcs);

        // assert
        barMock.AssertWasCalled(x => x.Add(uid, ref arg), y => y.IgnoreArguments());
    }

这是我发现的错误:

Rhino.Mocks.Exceptions.ExpectationViolationException : ICommandBar.Add(ESRI.ArcGIS.esriSystem.UIDClass, 0); 预期 #0,实际 #1。

我已经尝试了很多方法,但它根本不起作用。构建方法实现如下。这仅接收要构建的功能列表和具有相关功能的用户。如果他有一个函数,它应该被构建,使用 add 方法。

    public void Build(Usuario u, List<IFunctionality> funcsToBuild)
    {
        if (u == null)
            throw new ArgumentNullException("u");

        if (funcsToBuild == null)
            throw new ArgumentNullException("funcsToBuild");

        if (u.PRF_PERFIS == null || u.PRF_PERFIS.Count <= 0)
            return;

        var functionList = (from funcs in funcsToBuild
                            select funcs.FunctionDescription).ToList();

        var userFuncs = (from profile in u.PRF_PERFIS
                         from functionality in profile.FNC_FUNCIONALIDADES
                         where functionality.FNC_FL_ATIVO.HasValue && functionality.FNC_FL_ATIVO.Value && functionList.Contains(functionality.FNC_DE_FUNCIONALIDADE)
                         select new FunctionalityAttribute((int)functionality.FNC_NU_ID.Value,functionality.FNC_NO_CHAVE, functionality.FNC_DE_FUNCIONALIDADE, "SGIGT", true, "")).Cast<IFunctionality>().OrderBy(x => x.FunctionId).ToList();

        for (int index = 0; index < userFuncs.Count; index++)
        {
            IFunctionality t = userFuncs[index];
            object i = index;
            var functionality = t;
            var uid = new UIDClass() {Value = functionality.FunctionDescription};
            var ci = _commandBar.Add(uid, ref i);
        }
    }

有人可以帮助我吗?

4

2 回答 2

8

您可以使用 Arg<> 来匹配对 Out/Ref 参数的期望。如果您不关心实际值,则可以使用以下内容:

barMock.AssertWasCalled(x => 
              x.Add(Arg<UIDClass>.IsAnything(), 
              ref Arg<object>.Ref(Is.Anything(), null).Dummy);

如果您确实关心匹配输入/输出值,那么您可以使用它来代替:

barMock.AssertWasCalled(x => 
              x.Add(Arg<UIDClass>.Is.Equal(uid), 
              ref Arg<object>.Ref(Is.Same(input), output).Dummy);

我认为您的测试很可能失败,因为 uid 与传递给 ICommandBar 的实例不同,而不是 Ref 参数的特定问题。您可以通过使用 Equals 来解决这个问题,如上所示,而不是使用引用相等。

如果所有其他方法都失败并且 UIDClass 没有正确实现 equals,您始终可以使用匹配的谓词:

barMock.AssertWasCalled(x => 
              x.Add(Arg<UIDClass>.Is.Matching(
                    delegate(UIDClass u) { return u.Value == uid.Value; }
              ), 
              ref Arg<object>.Ref(Is.Same(input), output).Dummy);
于 2012-10-16T21:59:33.220 回答
1
    [Fact]
    public void Test_Ref()
    {
        var barMock = MockRepository.GenerateMock<IDoSomething>();

        Composer composer = new Composer(barMock);

        int number = 12;

        composer.addStuff(0, number);

        barMock.AssertWasCalled(x => x.Add(0, ref number), 
            y=>y.IgnoreArguments().Repeat.Times(1));
    }

    public class Composer
    {
        private IDoSomething dosomething;

        public Composer(IDoSomething doSomething)
        {
            this.dosomething = dosomething;
        }

        public void addStuff(int id, int value)
        {
            dosomething.Add(id, ref value);
        }

    }

    public interface IDoSomething
    {
        void Add(int id, ref int value);
    }

好吧,我认为这个问题可能与 MockRepository.GenerateStrictMock() 与 MockRepository.GenerateMock(); 然后在 IMethodoptions 上添加 Repeat.Times(1)。您应该能够确保使用此代码适当地根据 func 列表中的项目数调用 Add 。

于 2012-10-16T22:19:09.863 回答