Ok so i just got an assignment where i have to perform unit testing on a class with a private constructor.
Now how am i suppose to do unit testing without initializing a class when all the methods are also non static.
Is there any way i can do unit testing(without reflection)on a class with a private constructor ?
If you cannot make the class public, you can still test it easily by creating an instance of it this way:
var anInstance = (YourPrivateClass)Activator.CreateInstance(typeof(YourPrivateClass), true);
This will give you an instance of your class that you can then populate.
Another helpful testing bit is if you have internal methods (not private), you can access them by making internals visible to your test class. You add this line in assemblyinfo.cs of the class with the internal methods:
[assembly: InternalsVisibleTo("YourSolution.Tests")]
If this class has a private constructor, is this to be used publicly? If not, it may be best not to unit test it. If this is the case, the code that is public should test this code in itself by calling it.
Unit testing is there to test what is to be used by the public - by interfacing code in between application layers for instance. Take an input, I want this output. That is really what unit testing is about. Unit testing doesn't care what is in the actual method. As long as it returns what you want, performs the desired action, you have a pass.
You should be testing through a public API -- there must be some way that the class you want to test is instantiated and used.
Unit tests are typically written and run to ensure that code meets its design and behaves as intended.
Creating a non-static class on which you cannot create an instance i.e. private constructor(s) only, might never be useful, in otherwords its is never Unit Testable.
In order to be Unit testable:
You should be able to create an instance of the class.
Testable Function should be either Public or Internal.
You could test Internal function by making your assembly as a Friend Assembly
It might be a singleton and you don't want the public constructor for the class.
Decorate the constructor with:
[ExcludeFromCodeCoverage]
Related
I got a unit test (MStest)
There is a test class that has a lot of test methods.
If I run all methods from TestExplorer, each method will invoke the constructor.
Is there any way to save TestClass instance across all of these methods?
well, there are multiple different attributes that indicate when a method should be invoked. When you want a setup to run only once for all tests, you should use the ClassInitialize -attribute, not the constructor:
[TestClass]
class MyTests
{
[ClassInitialize]
public static void SetupTests(TestContext context) { ... }
}
Performing initializations from within the constructor is merely a bad idea, as every test-framework has its own plan on when and how often to invoke those. Instead you should use the attributes which are deterministic in their use.
If you need initialization to happen before every test, you may use the TestInitialize-attribute.
Context. I have interface IVehicle, class VehiclesFactory and private class Vehicle nested in the VehiclesFactory. Thus all code except the VehiclesFactory kwnows nothing about any implementations of the IVehicle.
Question. How should I unit test the Vehicle? And should I do it at all?
Assumption 1. I can make the Vehicle public. However this will allow the all code to write new VehiclesFactory.Vehicle(...) which I try to avoid.
Assumption 2. I can make a new public method in the VehiclesFactory, e. g., IVehicle ForUnitTests_Vehicle(...) which just calls the Vehicle constructor and passes its arguments to that constructor (allowing a unit test to supply necessary mocks). However this will allow the all code to call this strange method.
Assumption 3. Factories is a plague; use the new operator everywhere. However this will couple my code more tightly.
How should I unit test the Vehicle?
You can use reflection to create an instance of Vehicle class in your test project or make your Vehicle class internal and use InternalsVisibleToAttribute attribute to make it visible to your test project. Though switching from private to internal will make your class visible to all the code in the same project, so I'm not sure if it's acceptable for you.
And should I do it at all?
Up to you, if it contains application critical logic probably you should test it.
My class has a method like this:
internal virtual Something CreateSomething(){...}
It was done this way so that in testing I can stub CreateSomething() to return a mock object:
var something = ...; //some mock object
var t = MockRepository.GenerateStub<MyObject>();
t.Stub(x => x.CreateSomething()).Return(something);
This worked fine but now CreateSomething() is called in the class constructor, before it was called later on, so by the time I stub the method my object is already created.
Is there a workaround that doesn't involve changing the design, to pass stub methods in at construction time? If not I can consider changing the design to use construction-injection (which I'm sure some of you are itching to suggest anyway!) but I'd rather see if Rhino supports this use-case first.
There is no way to stub the method before it is invoked from its class constructor. This is C# limitation. And this is reasonable.
In general it is a bad practice to call virtual method from the constructor, because likely the result will not be what is expected. See details here: Virtual member call in a constructor.
So, I highly recommend to either make this method non-virtual, or avoid its invocation from the constructor.
Anyway in such situation it won't work as virtual.
Regarding you question about testing the method, which is called from constructor.
I presume, this is a private method. Otherwise it could be tested as a regular public method.
As it is private, then there is no need to test this particular method in isolation. I recommend to follow general approach in testing constructors and testing private methods: Do not test private methods.
Test the public visible effect instead. That could be:
Public property initialization
Mocked dependencies invocation or properties access
Exception thrown
etc.
Please also find more details about this topic by the links below:
Is it important to unit test a constructor?
Unit testing private methods in C#
I have a function which calls many functions internally. I see in tutorials that test methods are designed in such a way that only the return values of outer functions are checked. How can I check the values returned by internal functions.
Only the GetValues() methods values are tested. How can i check the working of other methods inside GetValues(). How can I check its working using unit testing?
[TestFixture]
public class Class1
{
[Test]
public void Tester()
{
TesterClass clasObj;
int a = clasObj.GetValues();
Assert.AreEqual(10,a);
}
}
How can i check its working using unit testing?
In unit tests you only care about the, well, the unit, under test. In this case it is the GetValues. Also, usually only the public methods are unit tested. Because it is only the public methods ( interface) that has to be tested and not the internal workings.
It also ensures that the tests are not brittle. If you change the way a private / internal method works, but will essentially make the public interfaces work the same ( this especially when you are using mocks, and not really in the kind of testing you are doing), you shouldn't really be facing failed unit tests.
In such cases, you should be making sure that your unit tests cover all code path through the public method being tested and the private / internal methods that are being called by the method under test.
Sometimes, you do want to test the internals and one way is to use the InternalsVisibleToAttribute and mark the test assembly as a "friend".
http://msdn.microsoft.com/en-us/library/system.runtime.compilerservices.internalsvisibletoattribute.aspx
Another way is to subclass the class you are testing ( possibly in your test assembly), and add a public wrapper method to the method to be tested and use this proxy class and the public wrapper for testing.
I think you can do this with some tools, like TypeMock, but there is a reason why most tools don't allow it. This is because it usually makes the tests very brittle, meaning that when you change the internal code of a class, the tests will break. Internal members should be encapsulated and that is a good thing. I would look at a design that is testable from its public interface.
Generally you want to avoid testing the internal implementations of code, this is so that you can refactor and not break any tests. However, if you want to test the inside of another object, then the answer is easy. By wanting to test private implementation, the code smell is that the current object under test is doing too much work. In turn violating such rules as the single responsibility principle.
Therefore split out GetValues into a new object that you can test, such as:
ExampleFormatter.FormatValues()
Now this would be a public class with a public method meaning you can easily test it. All GetValues has to do now is invoke FormatValues with the correct params. You could use a mock object to verify that this happens as expected. As this is now public, when can test such things as the formatting of the values are as we expect and so forth. Any time you find it hard to test some code it usually means the code is doing too much, break it out!
In our Core domain model design, we have got a class called "Category" whose constructor is internal by design. Since the constructor is internal, when writing unit test cases I won't be able to create the object of "Category".
So my question, is it a best practice to make the constructor public just for making the "Category" class testable? Or I shouldn't be testing that "Category", instead I should have tested the Class/method responsible for creating this object?
Ta,
Rajeesh
Don't make the constructor public only for the sake of unit tests. If from a design point you decided that it should be internal, leave it that way. Test the classes that invoke this constructor.
In .NET there's the InternalsVisibleToAttribute which allows you to expose internal members to unit tests.
TDD means Test-Driven Design, and a corrolary to this is that a constructor can't really be internal "by design" if you can't test it.
Consider why it's internal. This will tell you how to address the issue. You shouldn't make the constructor public just to be able to test it, but you should consider a design that makes it easy to create new instances.
Often, constructors are made internal to protect invariants, but you could just as well achieve the same goal with a public constructor that takes required input as constructor parameters.
public class MyClass
{
private readonly string requiredString;
public MyClass(string requiredString)
{
if (requiredString == null)
{
throw new ArgumentNullException("requiredString");
}
this.requiredString = requiredString;
}
}
Notice how the combination of the Guard Clause and the readonly keyword protects the invariant of the class. This is often a good alternative to internal constructors.
Another reason for having internal constructors is when you have a Factory Method that may return a polymorphic object, but once again, consider if it would be a problem to expose the constructor if it doesn't mean compromising invariants.
The beauty of TDD is that it forces us to take a good look at any design decision and be able to really justify each and every one of them. Consider the justification of making the constructor internal and then modfiy the API so that the type is easy to create.
Add
[assembly: InternalsVisibleTo("UnitTestAssembly")]
to your AssemblyInfo.cs. Then UnitTestAssembl.dll is able to call your internal methods. More info is available here.
You could consider creating a static factory method that is named
Category *ConstructCategory_ForUnitTest();
with which you can create the object just for the sake of testing it.
It is apparent from the name that it should not be used outside testing context, and code review can easily spot the 'illegal' use in production grade code.