c# – 使用Rhino Mock报告被调用的函数

我有一个依赖于外部模块的失败测试用例.

我想使用Rhino Mock生成一个关于被调用函数的报告.

我创建了一个说明我问题的最小例子:

using NUnit.Framework;
using Rhino.Mocks;
using System;

namespace StackOverflow_namespace
{
    public interface IUsefulService
    {
        object HiddenAmongManyCalls();
    }

    public class ThirdPartyBase
    {
        private int a = 42;

        public ThirdPartyBase(IUsefulService service)
        {
            object liveFastDieYoung = service.HiddenAmongManyCalls();
            liveFastDieYoung.Equals(a);
        }
    }

    public class MyParty : ThirdPartyBase
    {
        public MyParty(IUsefulService service) : base(service)
        {

        }
    }


    [TestFixture]
    class StackOverflow
    {
        [Test]
        public void Hypothetical()
        {
            IUsefulService service = MockRepository.GenerateMock<IUsefulService>();

            try
            {
                var party = new MyParty(service);
            }
            catch(Exception e)
            {
                string[] calls = MagicallyGetTheCallsThatWereMadeToTheMock();
                foreach(var call in calls)
                {
                    //with my visual studio testrunner for nunit 3 I can investigate stored console output
                    Console.WriteLine(call);
                }
                Assert.Fail("Excpexted no exception but was '" + e.GetType().Name + "': " + e.Message);
            }
        }

        private string[] MagicallyGetTheCallsThatWereMadeToTheMock()
        {
            return new[]
            {
                "This is where I am lost, I do not know how to get the calls from the repository."
            };
        }
    }
}

我试图在网上找到一些没有成功的东西.

Rhino Mocks是否记录了所有呼叫,我可以访问该列表吗?

编辑:

尝试验证Expectations不起作用,因为我正在寻找我没想到的电话.

我可以使用GetArgumentsForCallsMadeOn构建一个调用列表.我可以反思界面.我开始使用一种方法,但我目前无法看到如何将MethodInfo转换为Action< T>.

private IEnumerable<string> GetCallsList<Interface>(Interface rhinomock)
{
    Type interfaceType = typeof(Interface);
    List<MethodInfo> interfaceMethodInfos = new List<MethodInfo>();
    List<string> returnInfos = new List<string>();
    StringBuilder callbuilder = new StringBuilder();

    foreach (var property in interfaceType.GetProperties())
    {
        interfaceMethodInfos.Add(property.GetGetMethod());
        interfaceMethodInfos.Add(property.GetSetMethod());
    }
    foreach (var method in interfaceType.GetMethods())
    {
        interfaceMethodInfos.Add(method);
    }

    foreach (var methodinfo in interfaceMethodInfos)
    {
        Action<Interface> magic = null; //convert methodinfo into action - still missing
        var calls = rhinomock.GetArgumentsForCallsMadeOn(magic); //magic is currently null, here be crash
        foreach (var call in calls)
        {
            bool more = false;
            callbuilder.Clear().Append(interfaceType.Name).Append('.').Append(methodinfo.Name).Append('(');
            foreach (var parameter in call)
            {
                if (more){ callbuilder.Append(", "); }
                if (null == parameter) { callbuilder.Append("<null>"); }
                else { callbuilder.Append(parameter.ToString()); }
                more = true;
            }
            callbuilder.Append(')');
            string callInfo = callbuilder.ToString();
            returnInfos.Add(callInfo);
        }
    }
    return returnInfos;
}

最佳答案 我能够使用反射来获得我想要的输出.

这是测试失败的最小示例,输出包含所有方法调用.

using NUnit.Framework;
using Rhino.Mocks;
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Text;

namespace StackOverflow_namespace
{
    public interface IUsefulService
    {
        object HiddenAmongManyCalls();
        string TestCall2(string arg1, int arg2);
        string FULLACCESS { get; set; }
        string READONLY { get; }
    }

    public class ThirdPartyBase
    {
        private int a = 42;

        public ThirdPartyBase(IUsefulService service)
        {
            service.TestCall2("callA", 1);
            service.TestCall2("callB", 1);
            object liveFastDieYoung = service.HiddenAmongManyCalls();
            service.TestCall2("callA", 2);
            service.TestCall2("callB", 2);
            var a = service.FULLACCESS;
            var b = service.READONLY;
            service.FULLACCESS = "some";
            liveFastDieYoung.Equals(a);
        }
    }

    public class MyParty : ThirdPartyBase
    {
        public MyParty(IUsefulService service) : base(service)
        {

        }
    }


    [TestFixture]
    class StackOverflow
    {
        [Test]
        public void Hypothetical()
        {
            IUsefulService service = MockRepository.GenerateMock<IUsefulService>();

            try
            {
                var party = new MyParty(service);
            }
            catch (Exception e)
            {
                var calls = GetCallsList(service);
                foreach (var call in calls)
                {
                    //with my visual studio testrunner for nunit 3 I can investigate stored console output
                    Console.WriteLine(call);
                }
                Assert.Fail("Excpexted no exception but was '" + e.GetType().Name + "': " + e.Message);
            }
        }

        private IEnumerable<string> GetCallsList<Interface>(Interface rhinomock)
        {
            Type interfaceType = typeof(Interface);
            List<MethodInfo> interfaceMethodInfos = new List<MethodInfo>();
            List<string> returnInfos = new List<string>();
            StringBuilder callbuilder = new StringBuilder();

            foreach (var property in interfaceType.GetProperties())
            {
                AddMethodInfoIfValid(interfaceMethodInfos, property.GetGetMethod());
                AddMethodInfoIfValid(interfaceMethodInfos, property.GetSetMethod());
            }
            foreach (var method in interfaceType.GetMethods())
            {
                AddMethodInfoIfValid(interfaceMethodInfos, method);
            }

            foreach (var methodinfo in interfaceMethodInfos)
            {
                int paramcount = methodinfo.GetParameters().Length;
                object[] args = new object[paramcount];
                Action<Interface> lambdacall = (i) => methodinfo.Invoke(i, args); 
                var calls = rhinomock.GetArgumentsForCallsMadeOn(lambdacall);
                foreach (var call in calls)
                {
                    bool more = false;
                    callbuilder.Clear().Append(interfaceType.Name).Append('.').Append(methodinfo.Name).Append('(');
                    foreach (var parameter in call)
                    {
                        if (more) { callbuilder.Append(", "); }
                        if (null == parameter) { callbuilder.Append("<null>"); }
                        else {
                            callbuilder
                                .Append('(').Append(parameter.GetType().Name).Append(")'")
                                .Append(parameter.ToString()).Append("'");
                        }
                        more = true;
                    }
                    callbuilder.Append(')');
                    string callInfo = callbuilder.ToString();
                    returnInfos.Add(callInfo);
                }
            }
            return returnInfos;
        }

        private static void AddMethodInfoIfValid(List<MethodInfo> interfaceMethodInfos, MethodInfo methodinfo)
        {
            if (null != methodinfo)
            {
                interfaceMethodInfos.Add(methodinfo);
            }
        }
    }
}
点赞