bflemi3
bflemi3

Reputation: 6790

Store a delegate method as a member of class

I'm doing coded ui testing, basically unit testing for the ui, and I have created a TestObject class that stores a list of assertions to be performed against itself within the TestMethod that instantiates it.

public class TestObject {
    public string urlToTest;
    public List<Assertion> assertions;
}

public class Assertion {
    public List<SearchPropertyExpression> searchPropertyExpressions;
    public Action assertMethod;
    public string expectedValue; // <-- this works fine if I'll always call a method like AreEqual() where it has an expected value, but what if I want to store a method in assertMethod that has different arguments???
}

public class SearchPropertyExpression {
    public string expression;
    public string value;
}

I would like to store the assert method (for example: Assert.AreEqaul(object expected, object actual) that I want executed against that particular TestObject and call that later but I'm struggling to get something that is syntactically correct. I'm also struggling with how to pass the arguments for that delegate method (assertMethod) when it's actually called. All methods that I'll be calling are within Microsoft.VisualStudio.TestTools.UnitTesting.Assert. In the example below I would like to call Assert.AreEqaul() but any method with varying arguments could be called. Here's what I've got so far...

[TestMethod]
public void uiTestConnectionsEducationHomePage() {
    //instantiate test object
    TestObject testObject = new TestObject() {
        urlToTest = "/example/home.aspx",
        assertions = {
            new Assertion() {
                searchPropertyExpressions = {
                    new SearchPropertyExpression() {
                        expression = HtmlDiv.PropertyNames.Id,
                        value = "header"
                    }
                },
                assertMethod = Assert.AreEqual // <-- this is wrong,I'm thinking I need to tell assertMethod what arguments to expect here, lambda??
            }
        }
    };

    // get handle to browser and launch
    UiBrowserWindow uiBrowserWindow = new UiBrowserWindow();
    uiBrowserWindow.launchUrl(testObject.urlToTest);

    // assertions
    testObject.assertions.ForEach(x => {
        HtmlDiv htmlObject = new HtmlDiv();
        x.searchPropertyExpressions.ForEach(p => {
            htmlObject = uiBrowserWindow.uiHtmlDocument.searchHtmlElementByAttributeValue<HtmlDiv>(p.expression, p.value);
        });
        x.assertMethod; // <-- for this is example the arguments would be (htmlObject, "header").                   
    });
}

I think my real problem is that there is a design pattern here that could really help me but I'm not well versed in design patterns.

Upvotes: 1

Views: 2561

Answers (2)

BuggyCoder
BuggyCoder

Reputation: 36

you can do something like this if you want your delegate to point to any method definition:-

public delegate void MyAction(params object[] args);
public class Assertion
{
    public List<PropertyExpression> propertyExpressions;
    public MyAction assertMethod;
}
public void Test()
{
   var asser = new Assertion()
                    {
                        assertMethod = (vals) =>Assert.AreEqual(vals[0],vals[1]);
                        propertyExpressions = null
                    };
   var asser2 = new Assertion()
                    {
                        assertMethod = (vals)=>Assert.AreEqual((string)vals[0],(string)vals[1],(bool)vals[2]);
                        propertyExpressions = null
                    };

    asser.assertMethod(1, 1);//calling object,object overload
    asser2.assertMethod("ab", "cd", true);//calling string,string,bool overload
}

Upvotes: 0

Daniel Hilgarth
Daniel Hilgarth

Reputation: 174309

Your assertMethod delegate is of type Action which represents a method with a return type of void and no parameters, e.g. void Foo().
Assert.AreEqual has many overloads, the most universial being Assert.AreEqual(Object expected, Object actual). I suggest you use this and change your delegate accordingly:

Action<Object, Object> assertMethod;

Upvotes: 3

Related Questions