I am trying to test a method that has a using statement that creates a new concrete instance of the IDisposable type.
To do this I am trying to fake a private method that is executed in the constructor of an IDisposable type. I could change the code so that it was more easily testable, but I would like to know if this way is possible first.
So far I have got:
- Use reflection to get the MethodInfo objects that point at the private methods
- Create an Expression type based on the MethodInfo object
- Tell FakeItEasy to DoNothing if that Expression is executed
An example code that illustrates my problem
namespace FakeUsing
{
using System;
using System.Linq.Expressions;
using System.Runtime.Remoting.Messaging;
using FakeItEasy;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Reflection;
// Application under test
class Program
{
public bool success = false;
// Entry Point
static void Main(string[] args)
{
Program p = new Program();
p.Run();
}
// Method I would like to test
public void Run()
{
using (new Concrete("data"))
{
// Code I actually want to test.
success = true;
}
}
}
// Problem class that I cannot change
public class Concrete : IDisposable
{
public Concrete(string data)
{
PrivateCall();
}
private void PrivateCall()
{
// Some stuff that uses unmanaged resources
// I'm not interested in testing
DoStuff();
}
public void Dispose()
{
// Some stuff that uses unmanaged resources
// I'm not interested in testing
DoStuff();
}
private void DoStuff()
{
throw new NotImplementedException();
}
}
// Testing code
[TestClass]
public class UnitTests
{
[TestMethod]
public void TestRun()
{
// Arrange
Program p = new Program();
MethodInfo doStuffMethodInfo =
typeof(FakeUsing.Concrete)
.GetMethod("DoStuff", BindingFlags.Instance | BindingFlags.NonPublic);
// This is the line I cannot get to work.
MethodCallExpression doStuffMCE =
Expression.Call(???, doStuffMethodInfo, null);
A.CallTo(doStuffMCE).DoesNothing();
// Act
p.Run();
// Assert
Assert.IsTrue(p.success);
}
}
}
In FakeUsing.UnitTests.TestRun I cannot get around the creating the MethodCallExpression instance a I don't have the instance before hand.
Thanks
David