Visual Studio allows unit testing of private methods via an automatically generated accessor class. I have written a test of a private method that compiles successfully, but it fails at runtime. A fairly minimal version of the code and the test is:
//in project MyProj
class TypeA
{
private List<TypeB> myList = new List<TypeB>();
private class TypeB
{
public TypeB()
{
}
}
public TypeA()
{
}
private void MyFunc()
{
//processing of myList that changes state of instance
}
}
//in project TestMyProj
public void MyFuncTest()
{
TypeA_Accessor target = new TypeA_Accessor();
//following line is the one that throws exception
target.myList.Add(new TypeA_Accessor.TypeB());
target.MyFunc();
//check changed state of target
}
The runtime error is:
Object of type System.Collections.Generic.List`1[MyProj.TypeA.TypeA_Accessor+TypeB]' cannot be converted to type 'System.Collections.Generic.List`1[MyProj.TypeA.TypeA+TypeB]'.
According to intellisense - and hence I guess the compiler - target is of type TypeA_Accessor. But at runtime it is of type TypeA, and hence the list add fails.
Is there any way I can stop this error? Or, perhaps more likely, what other advice do other people have (I predict maybe "don't test private methods" and "don't have unit tests manipulate the state of objects").
You can use the PrivateObject class:
Class target = new Class();
PrivateObject obj = new PrivateObject(target);
var retVal = obj.Invoke("PrivateMethod");
Assert.AreEqual(expectedVal, retVal);
Note: PrivateObject and PrivateType are not available for projects targeting netcoreapp2.0 - GitHub Issue 366
“There is nothing called as standard or best practice, probably they are just popular opinions”.
Same holds true for this discussion as well.
It all depends on what you think is a unit , if you think UNIT is a class then you will only hit the public method. If you think UNIT is lines of code hitting private methods will not make you feel guilty.
If you want to invoke private methods you can use "PrivateObject" class and call the invoke method. You can watch this indepth youtube video ( http://www.youtube.com/watch?v=Vq6Gcs9LrPQ ) which shows how to use "PrivateObject" and also discusses if testing of private methods are logical or not.
Another thought here is to extend testing to "internal" classes/methods, giving more of a white-box sense of this testing. You can use InternalsVisibleTo attribute on the assembly to expose these to separate unit testing modules.
In combination with sealed class you can approach such encapsulation that test method are visible only from unittest assembly your methods. Consider that protected method in sealed class is de facto private.
[assembly: InternalsVisibleTo("MyCode.UnitTests")]
namespace MyCode.MyWatch
{
#pragma warning disable CS0628 //invalid because of InternalsVisibleTo
public sealed class MyWatch
{
Func<DateTime> _getNow = delegate () { return DateTime.Now; };
//construktor for testing purposes where you "can change DateTime.Now"
internal protected MyWatch(Func<DateTime> getNow)
{
_getNow = getNow;
}
public MyWatch()
{
}
}
}
And unit test:
namespace MyCode.UnitTests
{
[TestMethod]
public void TestminuteChanged()
{
//watch for traviling in time
DateTime baseTime = DateTime.Now;
DateTime nowforTesting = baseTime;
Func<DateTime> _getNowForTesting = delegate () { return nowforTesting; };
MyWatch myWatch= new MyWatch(_getNowForTesting );
nowforTesting = baseTime.AddMinute(1); //skip minute
//TODO check myWatch
}
[TestMethod]
public void TestStabilityOnFebruary29()
{
Func<DateTime> _getNowForTesting = delegate () { return new DateTime(2024, 2, 29); };
MyWatch myWatch= new MyWatch(_getNowForTesting );
//component does not crash in overlap year
}
}
One way to test private methods is through reflection. This applies to NUnit and XUnit, too:
MyObject objUnderTest = new MyObject();
MethodInfo methodInfo = typeof(MyObject).GetMethod("SomePrivateMethod", BindingFlags.NonPublic | BindingFlags.Instance);
object[] parameters = {"parameters here"};
methodInfo.Invoke(objUnderTest, parameters);
Ermh... Came along here with exactly the same problem: Test a simple, but pivotal private method. After reading this thread, it appears to be like "I want to drill this simple hole in this simple piece of metal, and I want to make sure the quality meets the specs", and then comes "Okay, this is not to easy. First of all, there is no proper tool to do so, but you could build a gravitational-wave observatory in your garden. Read my article at http://foobar.brigther-than-einstein.org/ First, of course, you have to attend some advanced quantum physics courses, then you need tons of ultra-cool nitrogenium, and then, of course, my book available at Amazon"...
In other words...
No, first things first.
Each and every method, may it private, internal, protected, public has to be testable. There has to be a way to implement such tests without such ado as was presented here.
Why? Exactly because of the architectural mentions done so far by some contributors. Perhaps a simple reiteration of software principles may clear up some missunderstandings.
In this case, the usual suspects are: OCP, SRP, and, as always, KIS.
But wait a minute. The idea of making everything publicly available is more of less political and a kind of an attitude. But. When it comes to code, even in then Open Source Community, this is no dogma. Instead, "hiding" something is good practice to make it easier to come familiar with a certain API. You would hide, for example, the very core calculations of your new-to-market digital thermometer building block--not to hide the maths behind the real measured curve to curious code readers, but to prevent your code from becoming dependent on some, perhaps suddenly important users who could not resist using your formerly private, internal, protected code to implement their own ideas.
What am I talking about?
private double TranslateMeasurementIntoLinear(double actualMeasurement);
It's easy to proclaim the Age of Aquarius or what is is been called nowadays, but if my piece of sensor gets from 1.0 to 2.0, the implementation of Translate... might change from a simple linear equation that is easily understandable and "re-usable" for everybody, to a pretty sophisticated calculation that uses analysis or whatever, and so I would break other's code. Why? Because they didn't understand the very priciples of software coding, not even KIS.
To make this fairy tale short: We need a simple way to test private methods--without ado.
First: Happy new year everyone!
Second: Rehearse your architect lessons.
Third: The "public" modifier is religion, not a solution.
Another option that has not been mentioned is just creating the unit test class as a child of the object that you are testing. NUnit Example:
[TestFixture]
public class UnitTests : ObjectWithPrivateMethods
{
[Test]
public void TestSomeProtectedMethod()
{
Assert.IsTrue(this.SomeProtectedMethod() == true, "Failed test, result false");
}
}
This would allow easy testing of private and protected (but not inherited private) methods, and it would allow you to keep all your tests separate from the real code so you aren't deploying test assemblies to production. Switching your private methods to protected methods would be acceptable in a lot of inherited objects, and it is a pretty simple change to make.
HOWEVER...
While this is an interesting approach to solving the problem of how to test hidden methods, I am unsure that I would advocate that this is the correct solution to the problem in all cases. It seems a little odd to be internally testing an object, and I suspect there might be some scenarios that this approach will blow up on you. (Immutable objects for example, might make some tests really hard).
While I mention this approach, I would suggest that this is more of a brainstormed suggestion than a legitimate solution. Take it with a grain of salt.
EDIT: I find it truly hilarious that people are voting this answer down, since I explicitly describe this as a bad idea. Does that mean that people are agreeing with me? I am so confused.....
From the book Working Effectively with Legacy Code:
"If we need to test a private method, we should make it public. If
making it public bothers us, in most cases, it means that our class is
doing too much and we ought to fix it."
The way to fix it, according to the author, is by creating a new class and adding the method as public.
The author explains further:
"Good design is testable, and design that isn't testable is bad."
So, within these limits, your only real option is to make the method public, either in the current or a new class.
I use this helper (object type extension)
public static TReturn CallPrivateMethod<TReturn>(
this object instance,
string methodName,
params object[] parameters)
{
Type type = instance.GetType();
BindingFlags bindingAttr = BindingFlags.NonPublic | BindingFlags.Instance;
MethodInfo method = type.GetMethod(methodName, bindingAttr);
return (TReturn)method.Invoke(instance, parameters);
}
You can call it like this
Calculator systemUnderTest = new Calculator();
int result = systemUnderTest.CallPrivateMethod<int>("PrivateAdd",1,8);
One of the advantages is that it uses generics to pre-determine return type.
It's 2022 now!
...and we have .NET6
While this does not really answer the question, my preferred approach these days is to collocate code and test in the same C# project, with naming convention like <ClassName>.Tests.cs. Then I use internal access modifier instead of private.
In the project file, I have something like this:
<ItemGroup Condition="'$(Configuration)' == 'Release'">
<Compile Remove="**\*.Tests.cs" />
</ItemGroup>
to exclude the test files in release builds. Modify as needed.
FAQ 1: But sometimes you want to also test code in Release (optimized) build.
Answer: I find it unnecessary. I trust that the compiler will do its job without messing up my intent. So far, I've had no reason to question its ability to do so.
FAQ 2: But I really want to keep the method (or class) private.
Answer: Lots of excellent solutions in this page to try out. In my experience, having access modifier set to internal is usually more than enough since the method (or class) won't be visible outside the project it's defined. Beyond that, there's nothing more to hide.
Extract private method to another class, test on that class; read more about SRP principle (Single Responsibility Principle)
It seem that you need extract to the private method to another class; in this should be public. Instead of trying to test on the private method, you should test public method of this another class.
We has the following scenario:
Class A
+ outputFile: Stream
- _someLogic(arg1, arg2)
We need to test the logic of _someLogic; but it seem that Class A take more role than it need(violate the SRP principle); just refactor into two classes
Class A1
+ A1(logicHandler: A2) # take A2 for handle logic
+ outputFile: Stream
Class A2
+ someLogic(arg1, arg2)
In this way someLogic could be test on A2; in A1 just create some fake A2 then inject to constructor to test that A2 is called to the function named someLogic.
public static class PrivateMethodTester
{
public static object InvokePrivateMethodWithReturnType<T>(this T testObject, string methodName, Type[] methodParamTypes, object[] parameters)
{
//shows that we want the nonpublic, static, or instance methods.
var flags = BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Instance;
//gets the method, but we need the methodparamtypes so that we don't accidentally get an ambiguous method with different params.
MethodInfo methodInfo = testObject.GetType().GetMethod(methodName, flags, null, methodParamTypes, null);
if (methodInfo == null)
{
throw new Exception("Unable to find method.");
}
//invokes our method on our object with the parameters.
var result = methodInfo.Invoke(testObject, parameters);
if (result is Task task)
{
//if it is a task, it won't resolve without forcing it to resolve, which means we won't get our exceptions.
task.GetAwaiter().GetResult();
}
return result;
}
}
Call it this way:
Type[] paramTypes = new Type[] { typeof(OrderTender), typeof(string) };
var parameters = new object[] { orderTender, OrderErrorReasonNames.FailedToCloneTransaction };
myClass.InvokePrivateMethodWithReturnType("myPrivateMethodName", paramTypes, parameters);
In VS 2005/2008 you can use private accessor to test private member,but this way was disappear in later version of VS
You can use nested classes to test private methods. For example (NUnit v3 is used):
internal static class A
{
// ... other code
private static Int32 Sum(Int32 a, Int32 b) => a + b;
[TestFixture]
private static class UnitTests
{
[Test]
public static void OnePlusTwoEqualsThree()
{
Assert.AreEqual(3, Sum(1, 2));
}
}
}
Furthermore tests related code can be moved to another file using 'partial class' feature, excluded from release builds using 'conditional compilation', etc. Advanced example:
File A.cs
internal static partial class A
{
// ... other code
private static Int32 Sum(Int32 a, Int32 b) => a + b;
}
File A.UnitTests.cs
#if UNIT_TESTING
partial class A
{
[TestFixture]
private static class UnitTests
{
[Test]
public static void OnePlusTwoEqualsThree()
{
Assert.AreEqual(3, Sum(1, 2));
}
}
}
#endif
I had another approach that it works for me. because I always run my tests in debug mode so I used #if DEBUG to add public before my private method. so my private method is like this:
public class Test
{
#if (DEBUG)
public
#endif
string PrivateMehtod()
{
return "PrivateMehtod called";
}
}
Sadly there is no PrivateObject class in .net6
However I wrote a small extension method capable of invoking private methods using reflection.
Have a look at the sample code:
class Test
{
private string GetStr(string x, int y) => $"Success! {x} {y}";
}
var test = new Test();
var res = test.Invoke<string>("GetStr", "testparam", 123);
Console.WriteLine(res); // "Success! testparam 123"
And here is the implementation of the extension method:
/// <summary>
/// Invokes a private/public method on an object. Useful for unit testing.
/// </summary>
/// <typeparam name="T">Specifies the method invocation result type.</typeparam>
/// <param name="obj">The object containing the method.</param>
/// <param name="methodName">Name of the method.</param>
/// <param name="parameters">Parameters to pass to the method.</param>
/// <returns>The result of the method invocation.</returns>
/// <exception cref="ArgumentException">When no such method exists on the object.</exception>
/// <exception cref="ArgumentException">When the method invocation resulted in an object of different type, as the type param T.</exception>
/// <example>
/// class Test
/// {
/// private string GetStr(string x, int y) => $"Success! {x} {y}";
/// }
///
/// var test = new Test();
/// var res = test.Invoke<string>("GetStr", "testparam", 123);
/// Console.WriteLine(res); // "Success! testparam 123"
/// </example>
public static T Invoke<T>(this object obj, string methodName, params object[] parameters)
{
var method = obj.GetType().GetMethod(methodName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
if (method == null)
{
throw new ArgumentException($"No private method \"{methodName}\" found in class \"{obj.GetType().Name}\"");
}
var res = method.Invoke(obj, parameters);
if (res is T)
{
return (T)res;
}
throw new ArgumentException($"Bad type parameter. Type parameter is of type \"{typeof(T).Name}\", whereas method invocation result is of type \"{res.GetType().Name}\"");
}
If PrivateObject is not available and if the class under test is not a sealed class, you can make the methods and properties you want to expose protected. Create an inherited class in the unit test file with internal methods that expose the private methods/properties under test.
If the class under test is:
class MyClass{private string GetStr(string x, int y) => $"Success! {x} {y}";}
Change it to:
class MyClass{protected string GetStr(string x, int y) => $"Success! {x} {y}";}
In your unit test file create an inherited class something like this:
class MyClassExposed: MyClass
{
internal string ExposedGetStr(string x, int y)
{
return base.GetStr(x, y);
}
}
Now you can use the inherited class MyClassExposed to test the exposed methods and properties.
.NET doesn't allow use of Accessors anymore. You can use the code I posted here for an answer to a similar question.
How do you unit test private methods?
Related
This is a very specific problem. Not quite sure how to even word it. Basically I am implementing the unit of work and repository pattern, I have a dynamic object that I convert to an int, but if I use var it will throw an exception when trying to call the method.
I tried to remove all the trivial variables to this problem that I can. For some reason I only see it happen with these two design patterns. The exception I get is Additional information: 'BlackMagic.ITacoRepo' does not contain a definition for 'DoStuff'
Here is the code:
class BlackMagic
{
static void Main(string[] args)
{
dynamic obj = new ExpandoObject();
obj.I = 69;
UnitOfWork uow = new UnitOfWork();
int i1 = Convert.ToInt32(obj.I);
var i2 = Convert.ToInt32(obj.I);
if(i1.Equals(i2))
{
uow.TacoRepo.DoStuff(i1); // Works fine
uow.TacoRepo.DoStuff(i2); // Throws Exception
}
}
}
class UnitOfWork
{
public ITacoRepo TacoRepo { get; set; }
public UnitOfWork()
{
TacoRepo = new TacoRepo();
}
}
class Repo<T> : IRepo<T> where T : class
{
public void DoStuff(int i)
{
}
}
interface IRepo<T> where T : class
{
void DoStuff(int i);
}
class TacoRepo : Repo<Taco>, ITacoRepo
{
}
interface ITacoRepo : IRepo<Taco>
{
}
class Taco
{
}
EDIT: The main question I am trying to find an answer for, is why would the exception get thrown by calling DoStuff inside the unit of work (while using the repo) but not get thrown if DoStuff existed in the BlackMagic class.
This is one of the bugs I reported to Microsoft more than 5 years ago, soon after the dynamic was introduced. As far as I know, it is considered of a very low priority on their list, and might never be fixed.
Here are simple repro steps:
using System.Collections;
class C
{
static void Main()
{
object[] array = { };
IList list = new ArrayList();
list.CopyTo(array, 0); // Works okay
dynamic index = 0;
list.CopyTo(array, index); // Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: 'System.Collections.IList' does not contain a definition for 'CopyTo'
}
}
Here is an explanation of the problem. When a function member (a method or an indexer) is invoked on an expression whose static type is an interface type, and at least one of the arguments to the invocation is of the type dynamic (which means the complete member lookup -- type inference -- overload resolution process is postponed until runtime, and becomes a responsibility of the runtime binder rather than the compiler; only a partial set of checks is performed by the compiler based on incomplete type information), and the member being invoked is inherited by the interface from one of its base interfaces (rather than declared in the interface itself), then the runtime binder fails to properly traverse the tree of the base interfaces to find the inherited member, and throws an exception at runtime, reporting that the required member is not found. Note that it is only the runtime binder's fault -- the compiler properly accepted the invocation (but would reject it, if, for example, you made a typo in the method name).
A possible workaround: cast the expression you invoke a member on to the base interface that actually declares the member you are trying to invoke. For example, the program from the repro steps above could be fixed as follows:
using System.Collections;
class C
{
static void Main()
{
object[] array = { };
IList list = new ArrayList();
list.CopyTo(array, 0); // Works okay
dynamic index = 0;
((ICollection) list).CopyTo(array, index); // Works okay
}
}
Or, if possible, get rid of the dynamic dispatch completely by casting the argument(s) of type dynamic to the type specified in the invoked member's signature.
using System.Collections;
class C
{
static void Main()
{
object[] array = { };
IList list = new ArrayList();
list.CopyTo(array, 0); // Works okay
dynamic index = 0;
list.CopyTo(array, (int) index); // Works okay
}
}
Unfortunately, both workarounds might be not helpful if you really want overload resolution to happen at runtime, and among the possible candidates there are both members declared by the interface, and members inherited by it. You would probably need to invent some ad hoc solution in that case, or significantly refactor your program.
It looks like the RuntimeBinder doesn't traverse the inheritance hierarchy so it only looks in the immediate interface ITacoRepo for a definition of DoStuff.
If you make the the UnitOfWork use IRepo<Taco> instead of ITacoRepo, it is able to find the method definition.
I'm presently working on a project that includes tests with RhinoMocks mocked objects. Since upgrading to RhinoMocks 3.6.1 from 3.6.0 previously working project code is failing during testing. The issue seems to be caused by changed behavior of mock objects between versions. The generated Mock objects are now Castle Proxy objects that don't appear to be reflectable. Previously it was possible to gather MethodInfo from a mocked object via reflection, which no longer seems to be the case. Should I be setting up my mocks in a different way?
A greatly simplified example follows:
Given an interface to be mocked
public interface IValidator<in T>
{
bool Validate(T obj);
}
in testing code the mock is created with an expectation:
var validator = MockRepository.GenerateMock<IValidator<string>>();
validator.Expect(v => v.Validate(Arg<string>.Is.Equal("input")))
.Return(true);
...
// the validator object is then passed into a consumer and assertions
// are checked to be sure the consumer and validator appropriately
// behave (outside scope of question)
Within the consumer class reflection is done to get the "Validate" method from the interface in order to be invoked during standard execution:
var method = validator.GetType()
.GetMethod("Validate", BindingFlags.Public | BindingFlags.Instance);
The crux of the issue is method is now null when using the update version of RhinoMocks as reflection no longer seems to work.
The root of my issue is the inability to reflect on the proxy object generated by Rhino / Castle when all I have are instances an no ability to do explicit casting.
I know this might get me punched in the face.
But if you are in a generic class you could quite easily do something like
var method = typeof(IValidator<T>).GetType()
.GetMethod("Validate", BindingFlags.Public | BindingFlags.Instance);
Also if the project is very large and there are alot of tests and mocks, this may be a huge amount of rework :(
EDIT:
Ok round 2 :)
The problem seems to be in the fact that the mock is a dynamic class and does not actually seem to have that method.
How about instead of using GetMethod you create an interface (ITypeHelper) that has a number of wrapper methods for getting types and methods.
Normally these would just call the methods directly (so as to not cause any perfomance penalties), but during testing you could swap out your implementation of ITypeHelper for a MockTypeHelper (by changing the registration in the container or some other mechanisim).
public class RhinoMocks_33901386
{
//public static ITypeHelper TypeHelper = new TypeHelper();
//use when testing
public static ITypeHelper TypeHelper = new MockTypeHelper();
public static void Run()
{
var validator = MockRepository.GenerateMock<IValidator<string>>();
validator.Expect(v => v.Validate(Arg<string>.Is.Equal("input"))).Return(true);
var method = TypeHelper.GetMethod(validator.GetType(), "Validate");
var result = (bool) method.Invoke(validator, new object[] {"input"});
Console.WriteLine(result);
Console.WriteLine("Done");
Console.ReadLine();
}
}
public interface IValidator<in T>
{
bool Validate(T obj);
}
public interface ITypeHelper
{
MethodInfo GetMethod(Type self, string name);
}
public class TypeHelper : ITypeHelper
{
public virtual MethodInfo GetMethod(Type self, string name)
{
return self.GetMethod(name);
}
}
public class MockTypeHelper : ITypeHelper
{
public virtual MethodInfo GetMethod(Type self, string name)
{
if (typeof(IMockedObject).IsAssignableFrom(self) && self.BaseType == typeof(object))
{
self = self.GetInterfaces()
.First(x => x != typeof(IMockedObject) && x != typeof(ISerializable) && x != typeof(IProxyTargetAccessor));
}
return self.GetMethod(name);
}
}
Hope I'm getting warmer ;p
It seems like RihnoMocks or Castle DynamicProxy has changed how it works internally. As #sQuir3l pointed out, it seems to be using dynamic objects internally.
In this particular case you can work around the change by accessing the underlying interface type like this:
var method = ((IMockedObject)validator).ImplementedTypes
.Single(type => type == typeof(IValidator<string>))
.GetMethod("Validate", BindingFlags.Public | BindingFlags.Instance);
I have class Cache (wraps System.Runtime.Caching.MemoryCache) that I have created which has the following public methods:
bool Add(string key, object value)
bool Contains(string key)
How do I test the Contains() method without using the Add() method in the first place to add an item to the Cache??? Surely if I use the Add() method within the unit test for the Contains() method this would be wrong?
How do I test the Contains() method without using the Add() method in the first place to add an item to the Cache?
Assert that it returns false.
Surely if I use the Add() method within the unit test for the Contains() method this would be wrong?
Of course not. You're testing a unit which has a Contains() that differs in behaviour after you've called Add(). Not having tests for Contains() called after Add() would be wrong.
I think I understand your dilemma. You are asking if you use a new method to test another new method. Sort of testing an unknown with an unknown.
To me I would look at it as test isolation case of assumption. Let me explain...
The following applies if both methods are there and you are responsible for testing them.
In the first instance, you want to test the Add(,) method. In that case, I would 'assume' that all other methods work correctly. So in that case, I would run an Add(key,value) and check that it Asserts true, and then verify with a call to Contains(key) and ensure that it Asserts true. Even though Contains() is untested.
Then in the second instance, you assume that Add(,) is working properly and test the Contains() method. I always test based on the assumption that I've got blinkers on and testing something specific, a specific method, a specific class and run on the assumption that everything supporting required to run the test actually works.
In reality, this is not always the case and some of the supporting methods don't work as expected. But, the test will let you know. And that's what it's there for. To help reveal those issues.
You probably already have this test in mind but, here's a quick example where you can combine the testing of these two methods into a single test. Of course, you can split it into two tests (one thats Add() centric and one that's Contains() centric) but they will look fairly similar. I hope it helps.
public class SomeClass : MemoryCache
{
public SomeClass() : base("Test")
{
}
public bool Add(string key, object value)
{
return Add(key, value, DateTime.Now.AddDays(1));
}
}
[TestFixture]
public class TestSomeClass
{
[Test]
public void TestSomeClassMethod1()
{
var instance = new SomeClass();
const string key = "someKey";
Assert.IsFalse(instance.Contains(key));
Assert.IsTrue(instance.Add(key, new object()));
Assert.IsTrue(instance.Contains(key));
instance.Remove(key);
Assert.IsFalse(instance.Contains(key));
}
}
But in a pure TDD approach, you would do this:
Create the Add(,) method then write the following test:
[Test]
public void TestAdd()
{
var instance = new SomeClass();
const string key = "someKey";
Assert.IsTrue(instance.Add(key, new object()));
}
Then you would create the Contains() method and then write the following test:
[Test]
public void TestContains()
{
var instance = new SomeClass();
const string key = "someKey";
Assert.IsFalse(instance.Contains(key));
// A purest will say that you don't need the following Assert
// for the Add as it is not what you are testing.
// But I don't see any harm
Assert.IsTrue(instance.Add(key, new object()));
Assert.IsTrue(instance.Contains(key));
instance.Remove(key);
Assert.IsFalse(instance.Contains(key));
}
I have to write a unit test for some methods and I reached a method that returns void:
public virtual void ReadCities(string filename)
{
var engine = new FileHelperEngine(typeof (GeoDbCity));
_geoDbCities = engine.ReadFile(filename) as GeoDbCity[];
}
And my test method is:
[Test]
public void CheckIfCitiesWereRead()
{
var getGeoDbCitiesMock = new Moq.Mock<GeoDbReader>();
getGeoDbCitiesMock.Setup(y => y.ReadCities("ConstCities.csv"));
Assert.NotNull(getGeoDbCitiesMock.Object.ReadCities("ConstCities.csv"));
}
When assert is being called i'm getting an error:
Argument type 'void' is not assignable to parameter type 'object'.
My question is:
How to deal with void type methods and how test them? In this particular case how to test if ReadCities method actualy read something?
If a method does not return anything, then that method must have some side-effect such as changing a property of the class. Test that side-effect, e.g. test the value of said property.
You question actually consists of two questions: how to test void() methods, and how to test this ReadCities(string fileName) method.
In response to the first - In case your void method changes the internal state of the object, then that is what you can test for:
Example:
public class Person
{
public int age;
public void SetAge(int age)
{
this.age = age;
}
}
Then your test would be
var p = new Person();
p.SetAge(12);
Assert.AreEqual(p.age, 12);
In response to the question how to test that ReadCities method, well, you don't want to Mock it for one. You only mock the stuff you don't want to test - in a test.
Add a CSV file to your testproject ( type = content, action = copy always ) and use the DeploymentItem attribute to copy the CSV file into the test folder.
Then test with
var service = new Service();
service.ReadCities(pathToCsvFile);
Assert.NotNull(service.Cities);
// Actually - you want better assertions
So maybe ReadCities might be a void method, you can test the internal state of the object after, so the cities list.
If you don't expose the list of cities, there's another thing called the InternalsVisibleToAttribute which allows your tests to access private members. However, then we can get into a discussion of whether private members need to be tested in the first place.
In the strictest sense, if you ware testing only the ReadCities method, your mock shouldn't be testing that engine.ReadFile actually did something (you would have another unit test for that). You should isolate this method by mocking the call to engine.ReadFile (which I think you've done, but I'm not completely familiar with Moq).
In any case, what you'll likely need to do is create a public accessor for _geoDbCities that you can check in your Assert.
I'm creating a framework that contains a wrapper around a library (specifically SharpBrake) that performs all interaction with SharpBrake via reflection so there's no hard dependency on the library to 3rd parties of my framework.
If 3rd parties of my framework wants to use SharpBrake, they can just stuff the SharpBrake.dll into the bin folder, but if they don't, they can just forget about it. If my framework had explicit references to SharpBrake types, users of my framework would get exceptions during runtime of SharpBrake.dll missing, which I don't want.
So, my wrapper first loads SharpBrake.dll from disk, finds the AirbrakeClient type, and stores a delegate pointing to the AirbrakeClient.Send(AirbrakeNotice) method in a private field. My problem, however, is that since the Send() method takes an AirbrakeNotice object and I can't reference the AirbrakeNotice object directly, I need to somehow convert the Send() method to an Action<object>.
I have a strong feeling this isn't possible, but I want to explore all options before settling on exposing Delegate and using DynamicInvoke(), which I assume is far from optimal, performance-wise. What I would love to do is the following:
Type clientType = exportedTypes.FirstOrDefault(type => type.Name == "AirbrakeClient");
Type noticeType = exportedTypes.FirstOrDefault(type => type.Name == "AirbrakeNotice");
MethodInfo sendMethod = clientType.GetMethod("Send", new[] { noticeType });
object client = Activator.CreateInstance(clientType);
Type actionType = Expression.GetActionType(noticeType);
Delegate sendMethodDelegate = Delegate.CreateDelegate(actionType, client, sendMethod);
// This fails with an InvalidCastException:
Action<object> sendAction = (Action<object>)sendMethodDelegate;
However, this fails with the following exception:
System.InvalidCastException: Unable to cast object of type 'System.Action`1[SharpBrake.Serialization.AirbrakeNotice]' to type 'System.Action`1[System.Object]'.
Obviously, because sendMethodDelegate is an Action<AirbrakeNotice> and not an Action<object>. Since I can't mention AirbrakeNotice in my code, I'm forced to do this:
Action<object> sendAction = x => sendMethodDelegate.DynamicInvoke(x);
or just exposing the Delegate sendMethodDelegate directly. Is this possible? I know that there's chance of getting into situations where the object can be of a different type than AirbrakeNotice which would be bad, but seeing how much you can mess up with reflection anyway, I'm hoping there's a loophole somewhere.
If you're happy to use expression trees, it's reasonably simple:
ConstantExpression target = Expression.Constant(client, clientType);
ParameterExpression parameter = Expression.Parameter(typeof(object), "x");
Expression converted = Expression.Convert(parameter, noticeType);
Expression call = Expression.Call(target, sendMethod, converted);
Action<object> action = Expression.Lambda<Action<object>>(call, parameter)
.Compile();
I think that's what you want...
If you don't need below C# 4 support you can get much greater performance using the dynamic vs DynamicInvoke.
Action<dynamic> sendAction = x => sendMethodDelegate(x);
Actually I guess you wouldn't even need the above if you can use dynamic, because it would increase performance and simplify everything if you just did:
Type clientType = exportedTypes.FirstOrDefault(type => type.Name == "AirbrakeClient");
dynamic client = Activator.CreateInstance(clientType);
...
client.Send(anAirbrakeNotice);
But if you need to support .net 3.5 jon skeets answer with expression trees is definitely the way to go.
From my comment on the OP:
I'd avoid extended use of reflections if you are concerned about performance. If you can come up with an interface for the class(es) you are using, then I'd create one. Then write a wrapper that implements the interface by calling into the SharpBreak code, and stuff it in a separate DLL. Then dynamically load just your wrapper assembly and concrete wrapper type(s), and call into that interface. Then you don't have to do reflections at a method level.
I'm not sure all the classes you'd need, but here's a simple example of how you can hook into that library with loose coupling based on interfaces.
In your program's assembly:
public IExtensions
{
void SendToAirbrake(Exception exception);
}
public static AirbreakExtensions
{
private static IExtensions _impl;
static()
{
impl = new NullExtensions();
// Todo: Load if available here
}
public static void SendToAirbrake(this Exception exception)
{
_impl.SendToAirbrake(exception);
}
}
internal class NullExtensions : IExtensions // no-op fake
{
void SendToAirbrake(Exception exception)
{
}
}
In a load-if-available (via reflections) assembly
public ExtensionsAdapter : IExtensions
{
void SendToAirbrake(Exception exception)
{
SharpBrake.Extensions.SendToAirbrake(exception);
}
}
The advantage of this approach is that you only use reflections once (on load), and never touch it again. It is also simple to modify to use dependency injection, or mock objects (for testing).
Edit:
For other types it will take a bit more work.
You might need to use the Abstract Factory pattern to instantiate an AirbrakeNoticeBuilder, since you need to deal directly with the interface, and can't put constructors in interfaces.
public interface IAirbrakeNoticeBuilderFactory
{
IAirbrakeNoticeBuilder Create();
IAirbrakeNoticeBuilder Create(AirbrakeConfiguration configuration);
}
If you're dealing with custom Airbreak structures, you'll have even more work.
E.g. for the AirbrakeNoticeBuilder you will have to create duplicate POCO types for any related classes that you use.
public interface IAirbrakeNoticeBuilder
{
AirbrakeNotice Notice(Exception exception);
}
Since you're returning AirbrakeNotice, you might have to pull in nearly every POCO under the Serialization folder, depending on how much you use, and how much you pass back to the framework.
If you decide to copy the POCO code, including the whole object tree, you could look into using AutoMapper to convert to and from your POCO copies.
Alternately, if you don't use the values in the classes you're getting back, and just pass them back to the SharpBreak code, you could come up with some sort of opaque reference scheme that will use a dictionary of your opaque reference type to the actual POCO type. Then you don't have to copy the whole POCO object tree into your code, and you don't need to take as much runtime overhead to map the object trees back and forth:
public class AirbrakeNotice
{
// Note there is no implementation
}
internal class AirbreakNoticeMap
{
static AirbreakNoticeMap()
{
Map = new Dictionary<AirbreakNotice, SharpBreak.AirbreakNotice>();
}
public static Dictionary<AirbreakNotice, SharpBreak.AirbreakNotice> Map { get; }
}
public interface IAirbrakeClient
{
void Send(AirbrakeNotice notice);
// ...
}
internal class AirbrakeClientWrapper : IAirbrakeClient
{
private AirbrakeClient _airbrakeClient;
public void Send(AirbrakeNotice notice)
{
SharpBreak.AirbrakeNotice actualNotice = AirbreakNoticeMap.Map[notice];
_airbrakeClient.Send(actualNotice);
}
// ...
}
internal class AirbrakeNoticeBuilderWrapper : IAirbrakeNoticeBuilder
{
AirbrakeNoticeBuilder _airbrakeNoticeBuilder;
public AirbrakeNotice Notice(Exception exception)
{
SharpBreak.AirbrakeNotice actualNotice =
_airbrakeNoticeBuilder.Notice(exception);
AirbrakeNotice result = new AirbrakeNotice();
AirbreakNoticeMap.Map[result] = actualNotice;
return result;
}
// ...
}
Keep in mind that you only need to wrap the classes and parts of the public interface that you're going to use. The object will still behave the same internally, even if you don't wrap its entire public interface. This might mean you have to do less work, so think hard and try to wrap only what you need now, and what you know you're going to need in the future. Keep YAGNI in mind.
The programming style I have come to really like for problems like this is to write as much strongly-typed code as possible, and then hand off the logic from the dynamically-typed code to the strongly-typed code. So I would write your code like this:
//your code which gets types
Type clientType = exportedTypes.FirstOrDefault(type => type.Name == "AirbrakeClient");
Type noticeType = exportedTypes.FirstOrDefault(type => type.Name == "AirbrakeNotice");
//construct my helper object
var makeDelegateHelperType=typeof(MakeDelegateHelper<,>).MakeGenericType(clientType, noticeType);
var makeDelegateHelper=(MakeDelegateHelper)Activator.CreateInstance(makeDelegateHelperType);
//now I am in strongly-typed world again
var sendAction=makeDelegateHelper.MakeSendAction();
And this is the definition of the helper object, which is able to get away with fewer reflectiony calls.
public abstract class MakeDelegateHelper {
public abstract Action<object> MakeSendAction();
}
public class MakeDelegateHelper<TClient,TNotice> : MakeDelegateHelper where TClient : new() {
public override Action<object> MakeSendAction() {
var sendMethod = typeof(TClient).GetMethod("Send", new[] { typeof(TNotice) });
var client=new TClient();
var action=(Action<TNotice>)Delegate.CreateDelegate(typeof(Action<TNotice>), client, sendMethod);
return o => action((TNotice)o);
}
}