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?
I have a class, Foo, from a third party library that I check for equality against another instance using NUnit,
Assert.AreEqual(foo1, foo2);
When the objects are different I get the expected failure,
Expected: Foo
But was: Foo
But the error message isn't very helpful. I know NUnit uses ToString to show the error message but I can't override that here.
Does NUnit provide an API to override this behaviour so I can supply my own ToString implementation? I can't see anything on the Assert.AreEqual and Assert.That APIs
You can add specific formatting code for any Type and NUnit will use it. See https://github.com/nunit/docs/wiki/TestContext#addformatter
This feature was added in NUnit 3.2.
This may not be a great approach, but you could wrap the values inside of another class, and override ToString() there. For instance, in your test fixture, create the following private class:
private class ValueWrapper
{
private readonly OtherClass _wrapped;
public ValueWrapper(OtherClass wrapped)
{
_wrapped = wrapped;
}
public override bool Equals(object obj)
{
// Compare the wrapped objects for equality.
// This needs some beefing up for null checks, type checks, etc.
return _wrapped.Equals(obj._wrapped);
}
public override string ToString()
{
return "whatever you like";
}
}
With this wrapper class in hand, you could then wrap your expected & actual values and pass this into the asserts. For a CollectionAssert, you'd do so by transforming each element in the collection into one of these, using a Select() LINQ clause.
Using the accepted answer I put together the following code to json-serialize my failed constraints (using Json.NET):
TestContext.AddFormatter(obj =>
{
if (obj == null)
return x => "";
return x => JsonConvert.SerializeObject(x);
});
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.
Seems to be a popular question but I haven't found the answer yet, so
To be short, I have a generic function that I need to perform unit test on it, say
public void T[] DoSomething<T>(T input1, T input2)
Now I need to test if this function works correctly for int, ArrayList, how can I write unit tests in this case, listing all the cases for T is not an option, I'm thinking of just test int and some class instance ?
I also try to use the auto generated unit test from VS2012, something looks like :
public void DoSomethingHelper<T>() {
T item1 = default(T);; // TODO: Initialize to an appropriate value
T item2 = default(T); // TODO: Initialize to an appropriate value
T[] expected = null; // TODO: Initialize to an appropriate value
T[] actual = SomeClass.DoSomething<T>(item1, item2);
Assert.AreEqual(expected, actual);
Assert.Inconclusive("Verify the correctness of this test method.");
}
[TestMethod()]
public void AddTest() {
AddTestHelper<GenericParameterHelper>();
}
which is even more confusing to me, what should i put in DoSomethingHelper to initialize variables ? an int, a string or something ?
Can anyone help ? I've heard of Pex and others, but still no one provided me a sample unit test code for this simple function.
You might want to check NUnit’s Generic Test Fixtures, for testing with multiple implementations of T
First of all, think about the following: Why are you creating that function generic?
If you are writing a generic function/method, it shouldn't care about the implementation of the type it is working with. I mean, no more than what you specify in the generic class (eg. where T : IComparable<T>, new(), etc.)
So, my suggestion is that you create a dummy class that will fit the requirements of the generic type, and test with it. An example using NUnit:
class Sample {
//code here that will meet the requirements of T
//(eg. implement IComparable<T>, etc.)
}
[TestFixture]
class Tests {
[Test]
public void DoSomething() {
var sample1 = new Sample();
var sample2 = new Sample();
Sample[] result = DoSomething<Sample>(sample1, sample2);
Assert.AreEqual(2, result.Length);
Assert.AreEqual(result[0], sample1);
Assert.AreEqual(result[1], sample2);
}
}
Edit:
Think about it, and you'll see it works. You might think: "Well, but what if the body of DoSomething has something like...":
if (item1 is int) {
//do something silly here...
}
of course it will fail when testing it with int, and you won't notice it since you're testing with the Sample class, but think of it as if you were testing a function that sums two numbers, and you had something like:
if (x == 18374) {
//do something silly here...
}
You wouldn't identify it either.