Here's an example of testing Microsoft internal struct __DTString that
is part of mscorlib.dll.
[Test]
public void InternalConstructorTest()
{
DateTimeFormatInfo dtfi = new DateTimeFormatInfo();
Reflector _reflector = new Reflector("mscorlib.dll",
"System.__DTString", "MbUnit", dtfi);
Assert.AreEqual(true, _reflector.RunPrivateMethod("Match",
"MbUnit"));
}
Vadim
Much of the design of Reflector seems to be focused on accessing
non-public members but I can see that it is also of use accessing the
contents of late-bound types such as COM objects that do not have
registered wrappers.
How about we update the names of these methods like so:
GetField : Gets a public field
SetField : Sets a public field
GetProperty : Gets a public property
SetProperty : Sets a public property
InvokeMethod : Invokes a public method
AddEventHandler
RemoveEventHandler
GetNonPublicField : Gets a non-public field
SetNonPublicField : Sets a non-public field
GetNonPublicProperty : Gets a non-public property
SetNonPublicProperty : Sets a non-public property
InvokeNonPublicMethod : Invokes a non-public method
AddNonPublicEventHandler
RemoveNonPublicEventHandler
(Also provide static flavours like GetStaticField, SetStaticField,
etc...)
I also dislike having to specify the assembly partial name like that.
How about a bunch of factory methods?
Reflector Reflector.CreateInstance(Type type, params object[] args);
Reflector Reflector.CreateInstance(string typeName, params object[]
args);
Reflector Reflector.CreateInstanceFromAssembly(string assemblyName,
string typeName, params object[] args);
A few other utilities could come in handy (though these are just
one-liners):
Assembly Reflector.GetAssembly(string assemblyName);
Type Reflector.GetType(string type);
Type Reflector.GetTypeFromAssembly(string assemblyName, string
typeName);
Delegate Reflector.CreateDelegate(Type delegateType, object
targetObject, MethodInfo targetMethod);
It would also be useful to provide the following getters:
Type Type { get; } : Gets the type of the reflected object.
object Instance { get; } : Gets the contained instance.
Finally, method invocation should automatically unwrap Reflector
instances passed in as parameters before calling the method.
Jeff.
Sorry, it took me awhile to reply to your post. I was very busy at
work dealing with crisis. I barely had time to read (not to reply) my
emails.
> Just a thought, I think the naming conventions of Reflector are somewhat
> inconsistent.
I agree some naming conventions are inconsistent. Unfortunately, it's
not very easy to change the names because we don't know how many
people are using Reflector. What we can do is to decorate old methods
with Obsolete attribute and remove them in version 3.0. However, I
guess we need other people opinion.
Andrew, Do you have any ideas?
> It contains GetNonPublicVariable and GetPrivateVariable among other
> things.
GetNonPublicVariable is a static method where GetPrivateVariable is an
instance method.
I personally prefer to work with instance methods.
GetNonPublicVariable is decorated with Obsolete attribute (see snippet
of code below) and prefer method is GetNonPublicField.
[Obsolete("Use GetNonPublicField instead")]
public object GetPrivateVariable(string variableName)
> Much of the design of Reflector seems to be focused on accessing
> non-public members but I can see that it is also of use accessing the
> contents of late-bound types such as COM objects that do not have
> registered wrappers.
Ability to access public members is a free bonus that doesn't cost
much to implement; however, I don't see why people will use Reflector
to access public members when they can access the directly. Actually,
people might use Reflector, to access public members of non-public
class or struct. GetNonPublicXXX name was chosen on purpose. I
believe that this is a very good discussion. I'd like to here other
people opinion.
I have to run now but I'll try to talk more on this subject.
Jeff, thanks again for talking about this.
Vadim
> Cc: astopf...@gmail.com
> Reflector Reflector.CreateInstanceFromAssembly (string assemblyName,
What do you think about these names (Jeff suggested them for public
members only).
GetField : Gets a public/non-public/static field (Exists: needs to be
renamed)
SetField : Sets a public/non-public/static field (New: needs to be
created)
GetProperty : Gets a public/non-public/static property (Exists)
SetProperty : Sets a public/non-public/static property (New)
InvokeMethod : Invokes a public/non-public/static method (Exists)
AddEventHandler (New)
RemoveEventHandler (New)
I like suggestion about CreatInstance. The method below is fine.
CreateInstanceFromAssembly(string assemblyName, string typeName,
params object[] args);
we also can add these methods:
CreateInstanceFromAssembly(string assemblyName, string typeName);
CreateInstanceFromAssembly(Assembly assembly, string typeName);
CreateInstanceFromAssembly(Assembly assembly, string typeName, params
object[] args);
However, the methods below need to know from which assembly they need
to create instance.
CreateInstance(Type type, params object[] args);
CreateInstance(string typeName, params object[] args);
We can create an Assembly property. That means that a user needs to
set assembly before calling the two methods above. If assembly is not
set, we have to throw an exception. Is that what we want?
Here a list of utilities Jeff suggested:
Assembly Reflector.GetAssembly(string assemblyName);
Type Reflector.GetType(string type);
Type Reflector.GetTypeFromAssembly(string assemblyName, string
typeName);
Delegate Reflector.CreateDelegate(Type delegateType, object
targetObject, MethodInfo targetMethod);
Type Type { get; } : Gets the type of the reflected object.
object Instance { get; } : Gets the contained instance.
Do you think it's going to be need for them?
Vadim
Hi All,
I’m writing some new Custom Test Attributes (inheriting from DecoratorPatternAttribute) and I was wondering if there’s any way to get the test method from within my RunInvoker?
The reason I need this is I want my invoker to extract a resource from the assembly being tested. But at the time that the invoker is being invoked, the test using my custom attribute isn’t in the call stack. I figure this would be information that MbUnit would have at the moment, but it doesn’t appear to be passing that info to the invoker.
Is there something I’m missing?
Phil
Public Sub Reflect(ByVal tree As RunInvokerTree, ByVal parent As RunInvokerVertex, ByVal t As Type) Implements IRun.Reflect
Dim TestMethods As ICollection = TypeHelper.GetAttributedMethods(t, GetType(TestWithEachObjectAttribute))
Dim FixtureObjectProviders As Object() = t.GetCustomAttributes( GetType(ObjectProviderFixtureDecoratorAttribute), True)
Dim num1 As Integer
For num1 = 0 To FixtureObjectProviders.Length - 1
Dim attribute1 As ObjectProviderFixtureDecoratorAttribute = CType(FixtureObjectProviders(num1), ObjectProviderFixtureDecoratorAttribute)
Dim TestParameter As Object
For Each TestParameter In attribute1.GetData.ParameterCollection
Dim TestMethodInfo As MethodInfo
For Each TestMethodInfo In TestMethods
Dim attribute2 As TestWithEachObjectAttribute = CType(TypeHelper.GetFirstCustomAttribute (TestMethodInfo, GetType(TestWithEachObjectAttribute)), TestWithEachObjectAttribute)
Dim invoker1 As IRunInvoker = New TestWithEachObjectRunInvoker( Me, TestMethodInfo, attribute2, TestParameter)
invoker1 = DecoratorPatternAttribute.DecoreInvoker(TestMethodInfo, invoker1)
tree.AddChild(parent, invoker1)
Next
Next
Next num1
End Sub
Thanks Jay? So is that what VB looks like these days? ;)
I noticed the “Reflect” method but wasn’t sure what it was used for. Is there any documentation for it? I’m assuming it is called before Execute and gives me the ability to pass information to the Invoker about the code being tested?
What I’m trying to do is something like this:
[Test]
[ExtractResource(“Resource.Name”, “d:\Destination”)]
Public void SomeTest()
{}
Which would extract the specified resource into the destination folder. Could be a useful test attribute to contribute to MbUnit, unless someone already did it. The resource would be embedded in the same assembly as the unit test. I guess I might also need an override that allows you to specify the assembly to extract from.
Phil
Hi All,
With some friendly help from Jay, I got my new test decorator working.
http://haacked.com/archive/2007/04/27/extract-embedded-resources-with-an-attribute-in-mbunit.aspx
My hope is this finds its way into a future release of MbUnit. *hint* *hint*.
Or at least some sort of MbUnitContrib project. :D
Phil
Indicating public vs. non-public is useful for documentation purposes.
Indicating static usage in some fashion is essential since the calling
conventions are different. Does an instance of Reflector exist when
accessing static members, or do we just call static functions on
Reflector with a suitable Type? Or... how about making a TypeReflector
to wrap a Type with extra convenience methods for accessing statics and
then make Reflector just wrap intances.
In any case, an assembly is not strictly required for implementing
CreateInstance with just a Type or typeName. These can be implemented a
bit like this:
static Reflector CreateInstance(Type type, params object[]
constructorArgs)
{
return Wrap(Activator.CreateInstance(type,
BindingFlags.CreateInstance | BindingFlags.Public |
BindingFlags.NonPublic |BindingFlags.Instance, null,
UnwrapArray(constructorArgs)));
}
// assumes typename is assembly qualified or in the currently executing
assembly
static Reflector CreateInstance(string typeName, params object[]
constructorArgs)
{
return CreateInstance(Type.GetType(typeName, true),
constructorArgs));
}
static object[] UnwrapArray(object[] values)
{
if (values == null)
return null;
return Array.ConvertAll(values, delegate(object value)
{
Reflector reflectedValue = value as Reflector;
return reflectedValue != null ? reflectedValue.Instance : value;
});
}
static Reflector Wrap(object value)
{
Reflector reflectedValue = value as Reflector;
return reflectedValue != null ? reflectedValue : new
Reflector(reflectedValue);
}
Additional helpers would be useful for situations involving private
nested types, creating instances of privately typed delegates, and
various other special cases.
Jeff.
-----Original Message-----
From: MbUn...@googlegroups.com [mailto:MbUn...@googlegroups.com] On
Behalf Of Vadim
Andrew,
Any idea when you're going to release next build? At my work people
want to use MbUnit to test non-public classes. It was checked in
about two weeks ago.
Vadim
> Vadim- Hide quoted text -
>
> - Show quoted text -