如何创建一个在c#中转发方法调用的代理对象?

时间:2011-06-13 06:34:52

标签: c# unit-testing selenium

我正在尝试使用selenium来运行测试;似乎没有一种好方法可以在多个浏览器上运行相同的单元测试集。

我读了这篇关于并行运行测试的帖子: http://slmoloch.blogspot.com/2009/12/design-of-selenium-tests-for-aspnet_19.html

但是,我正在使用visual studio单元测试框架。

我可以像这样创建一个代理类:

public class SeleniumProxy {
    private List<DefaultSelenium> targets;
    public SeleniumProxy() {
        targets = new List<DefaultSelenium>();
        targets.Add(new DefaultSelenium(... "firefox"...));
        targets.Add(new DefaultSelenium(... "iexplore"...));
    }
    public void Open(String url) {
        foreach (var i in targets) {
            i.Open(url);
        }
    }
    ...
}

我的问题是这个?如何在不必将整个类重写为代理的情况下完成它?

我想可能会将一个lamda传递给map参数,或者传递一个带有方法名称来调用的函数,但这些看起来都是非常蹩脚的想法。

我真正想要的是添加如下成员:

public class SeleniumProxy {
    public dynamic proxy;
    ....
}

并调用它:

var selenium = getProxy();
selenium.proxy.Open("...");

c#是否允许这种动态对象的语法?

或者某种类的元处理程序,它们可以捕获没有这样的方法异常并手动处理它们?

基本上: 如何创建一个动态调用类内部成员的方法的代理对象?

(编辑:也许......在DefaultSelenium对象上使用反射并在每个条目的动态代理对象上创建函数存根...?)

2 个答案:

答案 0 :(得分:0)

如果我理解你的尝试,我认为你可以延长DynamicObject来实现这一目标。

class Proxy : System.Dynamic.DynamicObject
{
    public Proxy(object someWrappedObject) { ... }

    public override bool TryInvokeMember(System.Dynamic.InvokeMemberBinder binder, object[] args, out object result)
    {
      // Do whatever, binder.Name will be the called method name
    }
}

//Do whatever...会成为一些代码,它会在查找过程中使用binder.Name在某些其他对象的内部成员(通过反射,大概是反射)进行调用。

如果你需要包含那个简单方法调用的更好的东西,可以覆盖TryGetMemberTryGetIndex个方法。

您必须在构建后将Proxy的实例投射到dynamic以进行任意调用,就像处理ExpandoObject时一样。

答案 1 :(得分:0)

您可以利用继承并使用工厂方法在抽象基类中定义测试以创建您的selenium实例,然后为要建模的每种类型的浏览器继承此项。然后将使用适当的浏览器为每个继承的类运行测试。以NUnit为例:

public abstract class AbstractTests
{
    protected abstract DefaultSelenium CreateSelenium();

    [Test]
    public void TestSomethingA()
    {
        DefaulSelenium selenium = CreateSelenium();

        //Do some testing with selenium.
    }
}

[TestFixture]
public class IETests : AbstractTests
{
    protected override DefaultSelenium CreateSelenium()
    {
        return new DefaultSelenium("iexplore");
    }
}

[TestFixture]
public class FirefoxTests : AbstractTests
{
    protected override DefaultSelenium CreateSelenium()
    {
        return new DefaultSelenium("firefox");
    }
}