Reputation: 5535
I have a class with a private function that dozens of other public functions use.
This private function just wrap other private functions that call to third party with try-catch
private T TryCatchCallWrapper<T>(Func<T> method)
{
try
{
Login();
return method();
}
catch (ConnectionException e)
{
switch (e.ConnectionReason)
{
case ConnectionReasonEnum.Timeout:
throw new ...
}
}
catch (XException e)
{
throw ...
}
}
I want to test this wrap function to be sure it catches all exceptions correctly, but I don't like to test it again for each public function that use it. (however, i want to verify they call to this function (like mock.Verify())
What is the best practice to deal with that?
One option is to extract the wrapped function to another class, but I am not sure it's good solution since the wrapped function usages and relevance are just in the current class. thanks!
Upvotes: 2
Views: 301
Reputation: 11
I would suggest a refactor. Move the code that you want to test to separate class ExternalLibCaller and inject the caller object into main class. Then you can create:
tests for ExternalLibCaller to test reactions for exceptions,
tests for main class with ExternalLibCallerMock to check if SafeCall was executed,
Example:
public class ClassWithPrivateTryCatchCallWrapper
{
IExternalLibCaller externalLibCaller;
public ClassWithPrivateTryCatchCallWrapper(IExternalLibCaller externalLibCaller)
{
this.externalLibCaller = externalLibCaller;
}
private T SafeCallWithLogin<T>(Func<T> method)
{
externalLibCaller.SafeCall(() =>
{
Login();
return method();
})
}
//use: SafeCallWithLogin(method)
//insted: TryCatchCallWrapper(method);
}
public interface IExternalLibCaller
{
T SafeCall<T>(Func<T> method)
}
public class ExternalLibCaller : IExternalLibCaller
{
public T SafeCall<T>(Func<T> method)
{
try
{
return method();
}
catch (ConnectionException e)
{
switch (e.ConnectionReason)
{
case ConnectionReasonEnum.Timeout:
throw new ...
}
}
catch (XException e)
{
throw ...
}
}
}
Upvotes: 1
Reputation: 22647
An option is to make the method internal, then expose it to your test suite using the InternalsVisibleToAttribute allowing your test suites to view internal members of your class.
Add the following to AssemblyInfo.cs
in your project,
[assembly: InternalsVisibleTo("mytestassembly)]
If your assembly is signed, it is a bit more work. You need to also sign your test assembly and add the PublicKey
of your test assembly to the attribute. You can get the public key using sn.exe -Tp mytestassembly.dll
from a Visual Studio Command Prompt, then add it to the attribute like this;
[assembly: InternalsVisibleTo("mytestassembly, PublicKey=002400000480000094" +
"000000060200000024000052534131000400000100010031eea" +
"370b1984bfa6d1ea760e1ca6065cee41a1a279ca234933fe977" +
"a096222c0e14f9e5a17d5689305c6d7f1206a85a53c48ca0100" +
"80799d6eeef61c98abd18767827dc05daea6b6fbd2e868410d9" +
"bee5e972a004ddd692dec8fa404ba4591e847a8cf35de21c2d3" +
"723bc8d775a66b594adeb967537729fe2a446b548cd57a6")]
You can also look at this answer for InternalsVisibleTo.
You also don't mention anything about your Login()
method. I assume that you are using dependency injection to mock out the functionality in the login?
Upvotes: 1
Reputation: 310
I think problem is in design. You should test only public functionlity directly and private should be tested indirectly. It is hard for me to say what is wrong using one wrapper function. But I want to link this question, maybe it will help to refactore your part of code. If you need mock.Verify() so use it:) Extract functionality to special class.
Upvotes: 2
Reputation: 1703
I think that the best option is to change it to be protected and to have an inherited class with a wrapper function to this function. this way the only change on your production code is the private function changed to protected and the new class can be part of your test project.
Upvotes: 1