views:

99

answers:

1

When I try to mock a class using Moq the method attribute gets inherited to the mock class, but not the parameter attribute.

Basically the row "let a = (ArgumentsAttribute) p.GetCustomAttributes(typeof (ArgumentsAttribute), true).SingleOrDefault()" doesnt return the attribute.. Run the code to see where it fails.

How do I make this test pass?

[TestFixture]
public class MyTests {
    [Test]
    public void shouldFindAndCallMethodWithAttributes() {
        var myInterface = new Mock<MyClass>();
        myInterface.Setup(x => x.MyMarkedMethod(1));
        myInterface.Setup(x => x.MyMarkedMethod(5));
        myInterface.Setup(x => x.MyMarkedMethod(9));

        var executor = new MarkedMethodExecutor();
        executor.FindAndCallMethodWithAttributes(myInterface.Object);

        myInterface.VerifyAll();
    }
}

public class MarkedMethodExecutor {
    public void FindAndCallMethodWithAttributes(object anObject) {
        var methods = from m in anObject.GetType().GetMethods()
                      where m.GetCustomAttributes(typeof (ExecuteMeAttribute), true).SingleOrDefault() != null
                      select m;
        foreach (var method in methods) {
            var callInfos = from p in method.GetParameters()
                            let a = (ArgumentsAttribute) p.GetCustomAttributes(typeof (ArgumentsAttribute), true).SingleOrDefault()
                            where a != null
                            select new {Parameter = p, Attribute = a};
            // assume its one argument here for simplicity..
            var attribute = callInfos.Single().Attribute;
            foreach (var argument in attribute.Arguments) {
                method.Invoke(anObject, new[] {argument});
            }
        }
    }
}

public class MyClass {
    [ExecuteMe]
    public virtual void MyMarkedMethod([Arguments(1, 5, 9)] int arg) {}
}

[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public class ExecuteMeAttribute : Attribute {}

[AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = true)]
public class ArgumentsAttribute : Attribute {
    public readonly object[] Arguments;

    public ArgumentsAttribute(params object[] arguments) {
        Arguments = arguments;
    }
}
A: 

I do not understand your problem: do you want to set the attributes?

You could use the function It.is(match). Maybe it helps: http://api.moq.me/html/5976987C.htm

Pablo Castilla
I want to be able to retrieve the attribute from the parameter, but when the class is mocked (a proxy is created by moq which inherits the class) the attribute is gone, although its set to be inherited.basically the row "let a = (ArgumentsAttribute) p.GetCustomAttributes(typeof (ArgumentsAttribute), true).SingleOrDefault()" doesnt return the attribute...
MatteS