Parsing function / method content using Reflection - c#

My unit testing frameworks consists of TestFixtures, TestMethods and Actions. Action is additional smaller container inside TestMethod, Actions comes from internal Dll written in our company. Actions are used inside methods like that:
[Test]
void TestMethod1()
{
Run(new Sleep { Seconds = 10 } );
}
I have to write an application, which collect all the information about fixtures, tests and actions from DLL. I have found how to enumerate test fixtures and test methods by reflection using type / method attributes.
But I have no idea how enumerate actions inside test methods.
Could you please help? Is it possible to do using reflection at all?
UPDATED:
See the accepted answer. Really cool library. Also you can look here ( WPF: Binding TreeView in MVVM way step by step tutorial ), if you are interested in how I created entity model for fixtures, tests and actions, and binded in MVVM way to TreeView.

Yes to extent.
Reflection will give you method body, than you need to disassemble the IL to read method body and obtain any information you want.
var bytes = mi.GetMethodBody().GetILAsByteArray();
One of possible tools to disassembe is Cecil
Check out Traverse a c# method and anazlye the method body for more links.

Instead of using reflection, why don't you roll out your own method that will log all Action executions.
void ExecuteAction(Action action)
{
//Log TestFixture, TestMethod, Action
//Execute actual action
}
[Test]
void TestMethod1()
{
ExecuteAction(Run(new Sleep { Seconds = 10 } ));
}
ExecuteAction method can be in a base or helper class

Thanks, Alexei Levenkov! Finally I have found a solution using your tip. Sharing. The only thing you should do -> download and reference Mono.Reflection.dll from https://github.com/jbevain/mono.reflection.
using System;
using System.Linq;
using System.Reflection;
using MINT;
using MbUnit.Framework;
using Mono.Reflection;
namespace TestDll
{
internal class Program
{
private static void Main(string[] args)
{
const string DllPath = #"d:\SprinterAutomation\Actions.Tests\bin\x86\Debug\Actions.Tests.dll";
Assembly assembly = Assembly.LoadFrom(DllPath);
// enumerating Fixtures
foreach (Type fixture in assembly.GetTypes().Where(t => t.GetCustomAttributes(typeof(TestFixtureAttribute), false).Length > 0))
{
Console.WriteLine(fixture.Name);
// enumerating Test Methods
foreach (var testMethod in fixture.GetMethods().Where(m => m.GetCustomAttributes(typeof(TestAttribute), false).Length > 0))
{
Console.WriteLine("\t" + testMethod.Name);
// filtering Actions
var instructions = testMethod.GetInstructions().Where(
i => i.OpCode.Name.Equals("newobj") && ((ConstructorInfo)i.Operand).DeclaringType.IsSubclassOf(typeof(BaseAction)));
// enumerating Actions!
foreach (Instruction action in instructions)
{
var constructroInfo = action.Operand as ConstructorInfo;
Console.WriteLine("\t\t" + constructroInfo.DeclaringType.Name);
}
}
}
}
}
}

Related

call same method that exists in multiple namespaces

this code works for me but there must be a better way to accomplish the same thing. The method Search exists in multiple namespaces. the correct namespace to use depends on code that is irrelevant just like some of the other code displayed. any thoughts on rewritting this better?
example namespaces used
MTG.Sites.Test1
MTG.Sites.Test2
static public async Task<List<Card>> Search(string sNamespace)
{
List<Card> rawCards = null;
try
{
Type t = Assembly.GetExecutingAssembly().GetType($"MTG.Sites.{sNamespace}");
if (t != null)
{
dynamic classInstance = Activator.CreateInstance(t);
rawCards = await classInstance.Search(httpClient);
}
}
catch(Exception ex)
{
log.Error(ex);
}
return rawCards;
}
the code i want to improve is the use of Assembly.GetExecutingAssembly().GetType("");
the short answer is to use AutoFac. the longer answer is a complete rewrite of how the code is used. i essentially need to register each Search class that exists in each Namespace that contains one. then using the AutoFac examples (AttributeMetadataExample & AspNetCoreExample), i was able to eliminate the need for reflection to find the Search method in each Namespace (passed as a string to GetType)

C# mocking Mock<StreamWriter>

I am new to C# mocking, I am trying to read some code and I got one of the tests failing, can you please explain to me what the below source code is trying to test and when will it fail?
Mock<StreamWriter> _streamWriterMock;
string[] expectedLines;
.
.
.
foreach (var line in expectedLines)
{
_streamWriterMock.Verify(a => a.Write(line), Times.Exactly(1));
}
Verify
You might want to check that the method under test was called, or even how many times that method was called
Just to reproduce the issue try this code
class Program
{
static void Main(string[] args)
{
var _streamWriterMock = new Mock<StreamWriter>("output.txt");
string[] expectedLines= new []{"test","test"};
foreach (var expectedLine in expectedLines)
{
_streamWriterMock.Object.Write(expectedLine);
}
foreach (var line in expectedLines)
{
_streamWriterMock.Verify(a=>a.Write(line),Times.Exactly(1));
}
}
}
In fact, if you try to mock your code with the array {"test","test"} you will get an exception
Expected invocation on the mock exactly 1 times, but was 2 times: a => a.Write("test")
But if your array is something like the following
string[] expectedLines= new []{"test","test1"};
Your mock will be executed correctly
So your verify will check if your method is called exactly once for the same input.
I think that the code main goal is to omit that you write the same output twice.
The test in your example iterates through all of the strings in your expectedLines array and checks that _streamWriterMock.Write(string value) is called on each of them exactly once. It will fail if Write is not called or is called more than once on any of the strings.
Update
Generally mocked methods must be virtual and depending on your mocking framework, the mock's method may need to be setup before being called so it may not be a valid test at all since StreamWriter is a concrete class and Write is not a virtual method.
Given the mocked StreamWriter
At best the foreach loop being used to verify with the mock that the each string in the expected lines array was called on the mocked stream writer's Write method exactly once during the exercising of the subject under test.
The test will fail if any of the expected lines are written more than once.
Review Moq: Quickstart - Verification
Take the following class as an example of a possible subject that depends on a StreamWriter
public class SubjectUnderTest {
private StringWriter stringWriter;
public SubjectUnderTest(StringWriter stringWriter) {
this.stringWriter = stringWriter;
}
public void WriteLines(string[] lines) {
foreach (var line in lines) {
this.stringWriter.Write(line);
}
}
}
The dependency would be mocked when testing and the functionality of the method under test can be verified in isolation.
For example.
[TestMethod]
public void TestMethod1() {
//Arrange
var _streamWriterMock = new Mock<StringWriter>();
string[] expectedLines = new[] { "line1", "line2" };
var subject = new SubjectUnderTest(_streamWriterMock.Object);
//Act
subject.WriteLines(expectedLines);
//Assert
foreach (var line in expectedLines) {
_streamWriterMock.Verify(a => a.Write(line), Times.Exactly(1));
}
}
If however, expectedLines had duplicates like { "lineN", "lineN" } Then the above test would fail as the verification is expecting the Write method to be called exactly one time with a given string value.

Is there anyway to detect what will be called from a method?

In C#, when I call a method, I want to be able to detect if it will (or could potentially) call something with a certain attribute.
For example, when, TheProgram.Run() get's called, I want to know that it will call a MyClass.DoTheWork, which has an attribute [IsRegistered], which calls a private method FormatTheResult() which also has the attribute [IsRegistered].
I've been thinking about it for a while and can't think how it could be achieved. I'm thinking, something like the invert of a stack trace, or registering components with an attribute or aspect, or perhaps leaning on MEF.
Is this possible?
This detection could happen at compile time or a run time, but ideally before the method with the attribute is executed.
Mocking frameworks can do this. It is useful for behavioural tests.
For example, given this setup:
public class Calculator {
private IHelpers _helperMethods;
public Calculator(IHelpers helper) {
_helperMethods = helper;
}
public int Add(int a, int b) {
if (_helperMethods.AboveZero(a) && _helperMethods.AboveZero(b)) {
return a + b;
}
throw new Exception("Argument not above zero");
}
}
public interface IHelpers {
bool AboveZero(int i);
}
Using Moq, you can verify (via a behavioural unit test) that IHelpers.AboveZero is called when calling the Add method like so:
[TestMethod]
public void When_Add_Called_Verify_AboveZero_Called_Too() {
// Arrange
var helperMock = new Mock<IHelpers>();
helperMock.Setup(x => x.AboveZero(It.IsAny<int>())).Returns(true);
var calc = new Calculator(helperMock.Object);
// Act
var result = calc.Add(1, 2);
// Assert
helperMock.Verify(x => x.AboveZero(It.IsAny<int>())); // verify that AboveZero was called.
}
The attributes are a different story though..
Is this what you were after?
(Please excuse any compiler errors.. this was typed by hand :/)
What you are probably looking for is Roslyn.
http://msdn.microsoft.com/en-au/vstudio/roslyn.aspx
What you can do with this is analize the syntax tree directly, so for your method in question you could access from the syntax tree all method calls that occur. Then you can follow that and check the method being called has that attribute.
Is pretty complex stuff, so I wont attempt a code sample for your particular scenario but I have used it before to analize multiple solitions and inject code.
It's pretty awesome here is a sample from the docs.
namespace GettingStartedCS
{
    class Program
    {
        static void Main(string[] args)
        {
            SyntaxTree tree = SyntaxTree.ParseCompilationUnit(
#"using System;
using System.Collections;
using System.Linq;
using System.Text;
namespace HelloWorld
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine(""Hello, World!"");
        }
    }
}");
            var root = (CompilationUnitSyntax)tree.GetRoot();
            var firstMember = root.Members[0];
            var helloWorldDeclaration = (NamespaceDeclarationSyntax)firstMember;
            var programDeclaration = (TypeDeclarationSyntax)helloWorldDeclaration.Members[0];
 
            var mainDeclaration = (MethodDeclarationSyntax)programDeclaration.Members[0];
 
            var argsParameter = mainDeclaration.ParameterList.Parameters[0];
        }
    }
}
Resharper does kind of what you want. Execute the menu command Resharper -> Inspect -> Outgoing calls, and then expand tree nodes ad infinitum until you reach the desired method. If you're using reflection or stuff like that, you're out of luck, I guess. The picture below is an example of how it works.
This is the way I've found to do it:
public static IList<MethodBase> GetCalledMethods(MethodBase methodBase)
{
IList<MethodBase> calledMethods = new List<MethodBase>();
var body = methodBase.GetMethodBody();
Module module = Assembly.GetExecutingAssembly().ManifestModule;
byte[] bytes = body.GetILAsByteArray();
using (var stream = new MemoryStream(bytes))
{
long streamLength = stream.Length;
using (var reader = new BinaryReader(stream))
{
while (reader.BaseStream.Position < streamLength)
{
byte instruction = reader.ReadByte();
if (instruction == OpCodes.Call.Value
|| instruction == OpCodes.Callvirt.Value
|| instruction == OpCodes.Newobj.Value)
{
int token = reader.ReadInt32();
var method = module.ResolveMethod(token);
calledMethods.Add(method);
}
}
}
}
return calledMethods;
}

How can I verify if a method is called inside another method

I tried to find an example of this but without success so that's is why I asked this question.
Lets start with some code. Here's my code:
class Dummy
{
public void DoDummyThings1()
{
Console.WriteLine("Sorry, I'm dummy 1...");
}
public void DoDummyThings2()
{
Console.WriteLine("Sorry, I'm dummy 2...");
}
public void DoDummyThings3()
{
Console.WriteLine("Sorry, I'm dummy 3...");
}
}
And my test code:
[TestClass]
public class UnitTest
{
private Dummy dum = new Dummy();
[TestInitialize()]
public void SetUp()
{
MethodInfo mi = typeof (UnitTest).GetMethod("TestDummy");
MethodBody mb = mi.GetMethodBody();
}
[TestMethod]
public void TestDummy()
{
this.dum.DoDummyThings1();
this.dum.DoDummyThings2();
this.dum.DoDummyThings3();
}
}
Here's what I'm trying to do. I want to, before execution of each test method, look to the test method and check if methods DoDummyThings1,DoDummyThings2 and DoDummyThings3 of Dummy class will be called or not.
The purpose of this is, depending of which DoDummyThingsX methods are called, I want to inject different implementation somewhere deep inside the code to modify during runtime the behavior of some class (swap the inject implementation of an interface for another one).
Can somebody explain me how to do this correctly (with lastest version of Cecil or something else for C#)?
Is there a way to do this without using the .dll files? (Currently, this is the only way I figured out how to do this but, using strings as "MyDllName.dll" and "MyNamespace.MyClassName" hard coded are not possible for me)
Other stackoverflow threads I'm already aware of:
Look if a method is called inside a method using reflection
How to determine which methods are called in a method?
Can I use reflection to inspect the code in a method?
Can anyone help me with a complete (but simple) example (if it's possible)?
Thank you!
This answer demonstrates how to determine which tests execute a Dummy method but does not answer:
inject different implementation somewhere deep inside the code to modify during runtime the behavior of some class
Reflection doesn't provide granular access to the IL Body of the unit test methods which you will need; however Cecil provides this functionality. The following linq returns a list of methods that internally call DoDummyThings1. The linq could be more efficient but I wanted to make it as clear as possible. The where clause is the important part.
//syntax based on version 0.9.5.4 (http://nuget.org/packages/Mono.Cecil/0.9.5.4)
using Mono.Cecil;
using Mono.Cecil.Cil;
//...
string assemblyPath = (#"path to your unit test assembly\MyTests.dll");
AssemblyDefinition asm = AssemblyDefinition.ReadAssembly(assemblyPath);
List<MethodDefinition> testsThatCallDummyMethods =
(from mod in asm.Modules
from t in mod.Types
from meth in t.Methods
where meth.HasBody
from instr in meth.Body.Instructions
let op = instr.Operand as MethodDefinition
where
instr.OpCode == OpCodes.Callvirt &&
op != null &&
op.DeclaringType.FullName ==
"Lib.Dummy" //namespace qualified type name
&& op.Name ==
"DoDummyThings1" //method names...
select meth)
.ToList();
Disassemble the test assembly using ILDasm to figure out the OpCodes / Operands. The relevant part of the TestDummy method will be something like:
//this.dum.DoDummyThings1();
IL_0001: ldarg.0
IL_0002: ldfld class Lib.Dummy Lib.UnitTest::dum
IL_0007: callvirt instance void Lib.Dummy::DoDummyThings1()

How to determine which methods are called in a method?

I'd like to list all the methods that are called from a specific method. E.g. if I have the following code:
public void test1() {
test2();
test3();
}
The list should contain test2() and test3(). It would be great if methods of the same class but also methods of another class could be listed.
Additionaly I'd like to find a way to detect which fields are used of a method:
public class A {
private String test1 = "";
private String test2 = "";
public void test() {
Console.WriteLine(test1);
}
}
Should therefore list test1.
I tried this using Mono.Cecil, but unfortunately I couldn't find lot of documentation about the project. So does anybody know how to do that?
Edit: I'd like to do it with Mono.Cecil because over its API I can directly use the results in my application. If I use built in tools in Visual Studio or similar, it's quite difficult to furhter process the results.
I haven't really worked with Cecil but the HowTo page shows how to enumerate the types, your problem only seems to require looping over the instructions for the ones your after: Call and Load Field. This sample code seems to handle the cases you mentioned but there may be more to it, you should probably check the other Call instructions too. If you make it recursive make sure you keep track of the methods you've already checked.
static void Main(string[] args)
{
var module = ModuleDefinition.ReadModule("CecilTest.exe");
var type = module.Types.First(x => x.Name == "A");
var method = type.Methods.First(x => x.Name == "test");
PrintMethods(method);
PrintFields(method);
Console.ReadLine();
}
public static void PrintMethods(MethodDefinition method)
{
Console.WriteLine(method.Name);
foreach (var instruction in method.Body.Instructions)
{
if (instruction.OpCode == OpCodes.Call)
{
MethodReference methodCall = instruction.Operand as MethodReference;
if(methodCall != null)
Console.WriteLine("\t" + methodCall.Name);
}
}
}
public static void PrintFields(MethodDefinition method)
{
Console.WriteLine(method.Name);
foreach (var instruction in method.Body.Instructions)
{
if (instruction.OpCode == OpCodes.Ldfld)
{
FieldReference field = instruction.Operand as FieldReference;
if (field != null)
Console.WriteLine("\t" + field.Name);
}
}
}
This can't be done simply using the reflection API within C#. Really you would need to parse the original source code which is probably not the kind of solution you're looking for. But for example this is how Visual Studio gets this kind of info to do refactoring.
You might get somewhere analysing the IL - along the lines of what Reflector does but that would be a huge piece of work I think.
you can use .NET Reflector tool if you want to pay. you could also take a look at this .NET Method Dependencies it gets tricky though, as you're going to be going into the IL. A third possible would be to use the macro engine in VS, it does have a facility to analyze code,CodeElement, I'm not sure if it can do dependencies though.

Categories

Resources