Reputation: 29332
I have an issue with a class that I'm trying to test. I've declared a private enum and I'm using that in a generic dictionary in the code. This enum has no meaning outside of this class but it's used in a private method. When I generated the code the accessor is written into the generic dictionary type, but throws an invalid cast exception when I try to use the test.
MyClass_Accessor target = new MyClass_Accessor();
Dictionary<MyClass_Accessor.MyEnum, long> dictionary = new Dictionary<MyClass_Accessor.MyEnum, long>();
dictionary.Add(MyClass_Accessor.Myenum.EnumValue, 1);
target.Method(dictionary); //Throws invalid cast exception here.
The exception is that the generic dictionary of accessor => enum, long cannot be converted to Myclass => enum, long.
Other than altering my working class, is there a way that I can test this method?
Upvotes: 1
Views: 1035
Reputation: 20131
I'll readily admit that under your circumstances this is a test that you may need to perform, in which case jrista's answer is the one to follow (InternalsVisibleTo).
When unit-testing however I don't think you are normally supposed to test the non-public API of classes. If this enum is private to the class, and therefore only used internally to the class, then it should not occur in any unit tests either.
The purpose of unit tests it to establish that the public (including virtual/abstract protected) API of your class performs as expected. By including tests that rely on an implementation detail such as this private enum, you essentially make it impossible to change the implementation in the future (for example into one that may not need an enum).
Upvotes: 0
Reputation: 32960
You can use the InternalsVisibleTo assembly attribute, and change your privates to internals. (If you can't change your private enum to an internal enum, then this won't work, but usually its an acceptable trade off.)
Assuming you have an assembly called AssemblyA that is being unit tested by AssemblyATest, and integration tested by AssemblyAIntegTest, you can stick the following in your AssemblyInfo.cs file:
using System.Runtime.CompilerServices;
// ...
[assembly: InternalsVisibleTo("AssemblyATest")]
[assembly: InternalsVisibleTo("AssemblyAIntegTest")]
If you sign your primary assemblies, you will also need to sign your test assemblies, and provide fully qualified, cultured, and primary keyed assembly names.
Upvotes: 4
Reputation: 9209
I'll admit that I haven't called private functions that also have private definitions in the way that you have, but looking at your code you don't appear to have selected a valid value from your dictionary object.
Shouldn't the code be something like?
target.Method(dictionary[0]);
Okay, after your comment below.
The following code is taken from a test using private methods of a class (PaDeviceManager), could it be adapted to your requirements?
PaDeviceManager paDeviceManager = PaDeviceManager.Create;
PrivateObject param0 = new PrivateObject(paDeviceManager);
PaDeviceManager_Accessor target = new PaDeviceManager_Accessor(param0);
PaDeviceManager_Accessor();
Upvotes: 0
Reputation: 21704
I have to admit that the question is not clear to me. But it looks like you need to test your private method through a public caller.
In most cases when you TDD, you create a public method to satisfy your test and then refactor it in private tests if you need.
Upvotes: 0