Store a delegate method as a member of class - c#

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.

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;

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
}

Related

Is there a way to write a method so that Method<A>(C obj) compiles? [duplicate]

I have a generic method like this (simplified version):
public static TResult PartialInference<T, TResult>(Func<T, TResult> action, object param)
{
return action((T)param);
}
In the above, param is of type object on purpose. This is part of the requirement.
When I fill in the types, I can call it like this:
var test1 = PartialInference<string, bool>(
p => p.EndsWith("!"), "Hello world!"
);
However, I'd like to use type inference. Preferably, I would like to write this:
var test2 = PartialInference<string>(
p => p.EndsWith("!"), "Hello world!"
);
But this does not compile. The best I came up with is this:
var test3 = PartialInference(
(string p) => p.EndsWith("!"), "Hello world!"
);
The reason I would like to have this as a type parameter and still have the correctly typed return type is because my actual calls look something like this:
var list1 = ComponentProvider.Perform(
(ITruckSchedule_StaffRepository p) => p.GetAllForTruckSchedule(this)
)
Which is very ugly and I would love to write as something like this:
var list2 = ComponentProvider.Perform<ITruckSchedule_StaffRepository>(
p => p.GetAllForTruckSchedule(this)
)
You can split t into a generic method on a generic type:
class Foo<TOuter> {
public static void Bar<TInner>(TInner arg) {...}
}
...
int x = 1;
Foo<string>.Bar(x);
Here the int is inferred but the string is explicit.
What you are trying to achieve is not possible. You need to specify both generic arguments or none of the them if inference is possible.
You can use reflection... like this below
Here is an example of how to call a extension method with two generic parameters.
We have to ways to execute the extension method:
a) Directly from an abstract base class
b) From an instance object that derived from that base class
Not mandatory to implement like so, but I found it very handy.
a) You must supply the two generic arguments as usual.
b) You already have one of the generic types since you are using an instance. The other generic parameter must by passed as type argument, you cannot pass it a second generic parameter due to ambiguity.
(see How to pass 2 generics types into an extension method)
public interface IEntityDto
{
// Not relevant to this example, how is defined , is just an interface, it could be removed, if your generic types don't need interface constraints
}
public interface IRowVersion
{
// Not relevant to this example, how is defined , is just an interface, it could be removed, if your generic types don't need interface constraints
}
public interface IPropertyMappingValue
{
// Not relevant to this example, how is defined , is just an interface, it could be removed, if your returned object don't need interface constraints
string Value { get; set; }
}
public class PropertyMappingValue : IPropertyMappingValue
{
// Not relevant to this example, how is defined , is just an object, returned by our extension method
public string Value { get; set; }
}
public abstract class EntityBase
{
public static IPropertyMappingValue GetPropertyMappingValue<TEntity, TEntityDto>(string name) where TEntity : class, IRowVersion where TEntityDto : class, IEntityDto => EntityExtensions.GetPropertyMappingValue<TEntity, TEntityDto>(name);
}
// Sample Class
public class Entity : IRowVersion
{
}
// Sample Class
public class EntityDto : EntityBase, IEntityDto
{
}
public static class EntityExtensions
{
public static IPropertyMappingValue GetPropertyMappingValue<TEntityDto>(this TEntityDto instance, Type entityType, string name) where TEntityDto : class, IEntityDto
{
if (!typeof(IRowVersion).IsAssignableFrom(entityType))
throw new ArgumentException($"{entityType} do not implements {typeof(IRowVersion)}");
var method = typeof(EntityExtensions).GetMethod(nameof(GetPropertyMappingValue), new[] { typeof(string) });
var typeArgs = new[] { entityType, typeof(TEntityDto) };
var constructed = method?.MakeGenericMethod(typeArgs);
var result = constructed?.Invoke(null, new object[] { name });
return result as IPropertyMappingValue;
}
public static IPropertyMappingValue GetPropertyMappingValue<TEntity, TEntityDto>(string name) where TEntity : class, IRowVersion where TEntityDto : class, IEntityDto
{
//TO DO YOUR JOB HERE TO GET A VALID RETURNED OBJECT, as this is an example I will return a fake
// THE CODE IS JUST AN EXAMPLE of doing something with the types, but is not relevant for this example
//
var foo = typeof(TEntityDto);
var bar = typeof(TEntity);
//
return new PropertyMappingValue { Value = name }; // returning just a fake object
}
}
public class UnitTest
{
private readonly ITestOutputHelper _console;
public UnitTest(ITestOutputHelper console)
{
_console = console;
}
[Fact]
public void Test()
{
var oneWayOfExecuting = EntityBase.GetPropertyMappingValue<Entity, EntityDto>("Hello world"); //using a abstract base
_console.WriteLine(oneWayOfExecuting.Value);
var entityDto = new EntityDto();
var anotherWayOfExecuting = entityDto.GetPropertyMappingValue(typeof(Entity), "Hello world"); //using the extension method
_console.WriteLine(anotherWayOfExecuting.Value);
Assert.Equal("Hello world", oneWayOfExecuting.Value);
Assert.Equal("Hello world", oneWayOfExecuting.Value);
}

Action calling a static method with an argument, without capturing this in C#

I want to store a method call in an action. That method is a static method, but with a string argument that varies. So I want to store "call StaticMethod with argument "myString" in an Action.
But... without capturing this.
I can store an anonymous method () => StaticMethod(myString) in the action , but this captures the action target (this). (Edit: it doesn't. See the accepted answer).
I can store the static method in the action, but then I'm missing the argument.
I could store the static method and the arguments separately, but due to technical reasons, this is cumbersome and ugly.
Do I have any other possibility?
[Edit]
In other words, I want to do this:
private void MyMethod(string myString){
var action = Call StaticMethod with argument myString.
}
And somewhere else, where I have access to action, but don't know anything about the string, or that there are arguments:
action.Invoke();
action can capture the string, but can't capture this (the call target of MyMethod).
Given the following assumptions:
myString is a local variable, or a parameter to the method (Not! a property or field)
StaticMethod is really a static method
There are no other delegates being constructed in the same method as you want to construct action
then the following:
public void M() {
string myString = "something";
Action action = () => StaticMethod(myString);
}
public static void StaticMethod(string value) { }
will be compiled as this:
[CompilerGenerated]
private sealed class <>c__DisplayClass0_0
{
public string myString;
internal void <M>b__0()
{
StaticMethod(myString);
}
}
public void M()
{
<>c__DisplayClass0_0 <>c__DisplayClass0_ = new <>c__DisplayClass0_0();
<>c__DisplayClass0_.myString = "something";
Action action = new Action(<>c__DisplayClass0_.<M>b__0);
}
As you can see, your lambda is lifted out to a generated display class, and myString is also lifted out from your method, going from a local variable to a field on that display class. This is the closure, and the object constructed in the M method will be the target of the action, and this closure will not capture this.
You can see this in action here: SharpLab
Note that small changes to your code will invalidate this as the assumptions change. For instance, if you also, in the same method, declare another delegate that also requires a closure and also requires access to this, then the same closure will be shared between the two delegates.
Example:
public void M() {
string myString = "something";
Action action = () => StaticMethod(myString);
Action otherAction = () => StaticMethod(Property);
}
public string Property => "Value";
Generates this code:
[CompilerGenerated]
private sealed class <>c__DisplayClass0_0
{
public string myString;
public C <>4__this;
internal void <M>b__0()
{
StaticMethod(myString);
}
internal void <M>b__1()
{
StaticMethod(<>4__this.Property);
}
}
public string Property
{
get
{
return "Value";
}
}
public void M()
{
<>c__DisplayClass0_0 <>c__DisplayClass0_ = new <>c__DisplayClass0_0();
<>c__DisplayClass0_.<>4__this = this;
<>c__DisplayClass0_.myString = "something";
Action action = new Action(<>c__DisplayClass0_.<M>b__0);
Action action2 = new Action(<>c__DisplayClass0_.<M>b__1);
}
As you can see, the same closure is used to support both delegates, and now both delegates has a reference to a closure that captures this.
If you can't define your action at call site at compile time e.:
Action a = () => StaticMethod("myString");
Then you will probably want to use expressions for this.
Example Code:
[Fact]
public void SampleActionWithoutThisScopeTests()
{
// Using Compile Time Action
Action compileTimeAction = () => MyStaticMethod("CompileTime myString");
compileTimeAction.Invoke();
// Using Compiled Expression
var myString = "Expression myString";
var methodInfo = this.GetType().GetMethod(nameof(MyStaticMethod), BindingFlags.Static | BindingFlags.Public);
var stringArgumentConstant = Expression.Constant(myString);
var callExpression = Expression.Call(null, methodInfo, stringArgumentConstant);
var lambda = Expression.Lambda<Action>(callExpression);
var action = lambda.Compile();
action.Invoke();
}
public static void MyStaticMethod(string input)
{
Console.WriteLine(input);
}
EDIT
If you can, and meet the requirements for the compiler-generated closure to not contain "this" via normal lambda syntax (see #Lasse V. Karlsen answer, then definitely use that approach!

Defining mocked response based on early void method calls to the same mocked object

Here's the class that I want to mock, massively truncated.
public class FooHandler
{
private FooInstance foo;
public void ConstructInstance(string fooSpecs)
{
foo = SomeMethod(fooSpecs);
}
public string GetSomeProperty()
{
return foo.SomeProperty();
}
}
In reality every method has a lot of internal logic. This is just the idea.
The code that I want to test requires a FooHandler, and it calls both methods, one after the other.
I want to mock my FooHandler to test whether my code calls it correctly.
var mockedFooHandler = new Mock<FooHandler>();
mockedFooHandler.Setup(x => x.ConstructInstance(EXAMPLE_FOO_SPEC));
mockedFooHandler.Setup(x => x.GetSomeProperty()).Returns(EXPECTED_PROPERTY);
Now, I want to tie these two setups together. I want to return different EXPECTED_PROPERTY's if the first method has been called with a different EXAMPLE_FOO_SPEC. The first method is void, and the second one takes no parameters. So I kind of want to set the internal state of the mocked object, the way the real one does. But the state is private.
Making several different mockedFooHandlers with their own programmed responses, to inject at different places, is not possible.
How should I go about that?
For void methods, can use Verify to validate that a method has been called in a certain way. example:
_mockedInstance.Verify(x => x.Method(expectedParameter), Times.Once);
If the method isn't called as expected, the verify will throw an exception thus failing the test. This should be called at the end of the test where you would normally assert your results.
https://github.com/Moq/moq4/wiki/Quickstart#verification
If I understand correctly, you want your mock to be able to give values back from one method, according to what a previous method receives from the class under test.
The following does that by capturing the parameter passed to the first mocked method, and the using that captured parameter as the input for a lambda function within the Returns method of the second mocked method.
public class UnitTest1
{
[TestMethod]
public void Can_Capture_Parameters()
{
var mockedFooHandler = new Mock<IFooHandler>();
string response = "";
// Here we use the moq Callback function to capture the paramter
mockedFooHandler.Setup(x => x.ConstructInstance(It.IsAny<string>()))
.Callback<string>(r => response = r);
mockedFooHandler.Setup(x => x.GetSomeProperty()).Returns("b");
mockedFooHandler.Object.ConstructInstance("testing");
Assert.AreEqual("testing", response);
}
[TestMethod]
public void Can_React_To_Parameters()
{
var mockedFooHandler = new Mock<IFooHandler>();
string response = "";
var responseDictionary = new Dictionary<string, string>()
{
{"first", "first response"},
{"second", "second response"},
{"third", "third response"}
};
mockedFooHandler.Setup(x => x.ConstructInstance(It.IsAny<string>()))
.Callback<string>(r => response = r);
// And here we use that captured parameter in a lambda. In this case using a dictionary to determine the desired response
mockedFooHandler.Setup(x => x.GetSomeProperty()).Returns(() => responseDictionary[response]);
mockedFooHandler.Object.ConstructInstance("first");
Assert.AreEqual("first response", mockedFooHandler.Object.GetSomeProperty());
}
}
public interface IFooHandler
{
void ConstructInstance(string fooSpecs);
string GetSomeProperty();
}
public class FooHandler : IFooHandler
{
public void ConstructInstance(string fooSpecs)
{
}
public string GetSomeProperty()
{
return "unexpected data";
}
}
I however agree with Kieran Devlin's comment, that the need to do this is almost certainly a code smell, and points to something wrong with your design.

c# Dispatching Extension Methods based on Value not Reference

Given the following 2 extension methods
public static string getIDPropertyName(this object value)
{
return "ID";
}
public static string getIDPropertyName<IDType>(this EntityRestIdentityDescriber<IDType> entityIdentityDescriber)
{
return entityIdentityDescriber.propertyNameDescribingID();
}
and the following 2 invocations
//arrange
object test = new CustomEntityRestModelIdentity();
//test.UserName = "KKK";
//act
var actual = test.getIDPropertyName(); //calls the first extension method
var actual2 = (test as CustomEntityRestModelIdentity).getIDPropertyName(); //calls the second extension method
How can I execute the second extension method even though its reference type is object but its value type is a EntityRestIdentityDescriber? I'm looking for static polymorphism.
try this
public static string getIDPropertyName(this object entityIdentityDescriber)
{
if(entityIdentityDescriber is EntityRestIdentityDescriber<IDType>)
return entityIdentityDescriber.propertyNameDescribingID();
else
return "id";
}
You need double dispatch.Double dispatch determine dispatch based on the actual type at runtime
public class IdPropertyNameResolver
{
public string GetIDPropertyName(object value)=>"ID";
public string GetIDPropertyName<T>(EntityRestIdentityDescriber<T> value)=>
value.propertyNameDescribingID();
}
//......do something
object o = new CustomEntityRestModelIdentity();
new IdPropertyNameResolver().GetIDPropertyName((dynamic)o);//CustomEntityRestModelIdentity id name
//......

How to test method with 'out' parameter(s)?

I am trying to write a unit test for a method that has out parameters. My method specifically is a TryParse method for my custom object. I am using .NET 4.5/5 with Visual Studio 2013. This allows me to fully realize private/internal and static objects using the PrivateType object. The one thing that seems to escape me is how to test for the out parameter as I cannot use this keyword in the InvokeStatic method. I am looking for the proper solution to test this architecture design.
The use for TryParse is part of a TypeConverter process as outlined in the WebAPI Parameter Binding post By Mike Wilson
public class MyFilter
{
public string Field { get; set; }
//... removed for brevity
internal static bool TryParse(string sourceValue, out MyFilter filter)
{
//... removed for brevity
}
}
public class MyFilterTests
{
[TestMethod]
[TestCategory("TryParse")]
public void TryParseWithTitleOnly()
{
var stringSource = "{field:'DATE.FIELD'}";
MyFilter tryParseOut = null;
var target = new PrivateType(typeof(MyFilter));
var tryParseReturn = target.InvokeStatic("TryParse", stringSource, tryParseOut);
var expectedOut = new MyFilter()
{
Field = "DATE.FIELD"
};
Assert.IsTrue((bool)tryParseReturn);
Assert.AreEqual(expectedOut, tryParseOut);
}
}
Personally, I'd use InternalsVisibleTo in order to make the method visible to your test code, but if you do want to use PrivateType, I'd expect you to be able to just create an object[] which you keep a reference to, pass it into InvokeStatic, and then get the value out again:
object[] args = new object[] { stringSource, null };
var tryParseReturn = target.InvokeStatic("TryParse", args);
...
// args[1] will have the value assigned to the out parameter
Assert.AreEqual(expectedOut, args[1]);
At least, I'd expect that to work - that's how reflection generally handles ref and out parameters.

Categories