Use reflection or a property when unit testing? - c#

This is a class I'm a bit concerned about. My goal is to unit test the addresses list:
public class LabelPrinter
{
private readonly IEnumerable<Address> _addresses;
public LabelPrinter(IEnumerable<Address> addresses)
{
_addresses = addresses;
}
public Document Create()
{
// ... Generate PDF, etc ...
}
}
So what is best:
Use reflection to inspect the private property, or
Since the original IEnumerable can be modified from outside anyway, make a public getter and test it instead?

In general, private members shouldn't be unit tested, since anything the class is doing with it's private members should somehow be reflected in the externally testable behavior of the object. In other words, who cares what's going on in there, as long as its external behavior is what it should be.
Unit testing private members also couples your tests to the internals of a class, making them more brittle. If you decide to use a more efficient collection later down the road, your tests will break, even though the behavior of the object hasn't changed. You especially want to avoid reflection, since looking up properties by name means your tests break if the property name ever changes.
In other words - if you need to test the Address class, do it from its own unit tests, rather than from the LabelPrinter's tests. If you must use one of your two methods, use the second one, rather than reflection.

What are you trying to test about the addresses list here? In the example code you've provided above your job is actually rather easy because you can inject the list through your constructor. So in your tests you can access the list as such and therefore don't necessarily need to expose it again:
[Test]
public void Test()
{
IEnumerable<Address> addresses = new List<Address>();
LabelPrinter printer = new LabelPrinter(addresses);
... // execute your test here
Assert.AreEqual(blah, addresses.get(0));
// or any other assertion you want to make on the addresses list
// created up above.
}

Particularly while learning unit testing, concerns about keeping fields private are trumped by easy testing and better coverage. Option 2.

Test Create and not the setter (which is effectively what you have here). I find testing setters/getters to be a bit of a waste of time. Esp. as most of the time the setter will have to be executed for some other test to work. They are also for the most part too simple to fail.
So rather than validate that LabelPrinter has a _addresses and it is Y, check that the output of Create includes the relevant details.

Related

Handling Multiple Mocks and Asserts in Unit Tests

I currently have a repository that is using Entity Framework for my CRUD operations.
This is injected into my service that needs to use this repo.
Using AutoMapper, I project the entity Model onto a Poco model and the poco gets returned by the service.
If my objects have multiple properties, what is a correct way to set-up and then assert my properties?
If my service has multiple repo dependencies what is the correct way to setup all my mocks? * - A class [setup] where all the mocks and objects are configured for these test fixtures?*****
I want to avoid having 10 tests and each test has 50 asserts on properties and dozens on mocks set-up for each test. This makes maintainability and readability difficult.
I have read Art of Unit Testing and did not discover any suggestions how to handle this case.
The tooling I am using is Rhino Mocks and NUnit.
I also found this on SO but it doesn't answer my question: Correctly Unit Test Service / Repository Interaction
Here is a sample that expresses what I am describing:
public void Save_ReturnSavedDocument()
{
//Simulate DB object
var repoResult = new EntityModel.Document()
{
DocumentId = 2,
Message = "TestMessage1",
Name = "Name1",
Email = "Email1",
Comment = "Comment1"
};
//Create mocks of Repo Methods - Might have many dependencies
var documentRepository = MockRepository.GenerateStub<IDocumentRepository>();
documentRepository.Stub(m => m.Get()).IgnoreArguments().Return(new List<EntityModel.Document>()
{
repoResult
}.AsQueryable());
documentRepository.Stub(a => a.Save(null, null)).IgnoreArguments().Return(repoResult);
//instantiate service and inject repo
var documentService = new DocumentService(documentRepository);
var savedDocument = documentService.Save(new Models.Document()
{
ID = 0,
DocumentTypeId = 1,
Message = "TestMessage1"
});
//Assert that properties are correctly mapped after save
Assert.AreEqual(repoResult.Message, savedDocument.Message);
Assert.AreEqual(repoResult.DocumentId, savedDocument.DocumentId);
Assert.AreEqual(repoResult.Name, savedDocument.Name);
Assert.AreEqual(repoResult.Email, savedDocument.Email);
Assert.AreEqual(repoResult.Comment, savedDocument.Comment);
//Many More properties here
}
First of all, each test should only have one assertion (unless the other validates the real one) e.q. if you want to assert that all elements of a list are distinct, you may want to assert first that the list is not empty. Otherwise you may get a false positive. In other cases there should only be one assert for each test. Why? If the test fails, it's name tells you exactly what is wrong. If you have multiple asserts and the first one fails you don't know if the rest was ok. All you know than is "something went wrong".
You say you don't want to setup all mocks/stubs in 10 tests. This is why most frameworks offer you a Setup method which runs before each test. This is where you can put most of your mocks configuration in one place and reuse it. In NUnit you just create a method and decorate it with a [SetUp] attribute.
If you want to test a method with different values of a parameter you can use NUnit's [TestCase] attributes. This is very elegant and you don't have to create multiple identical tests.
Now lets talk about the useful tools.
AutoFixture this is an amazing and very powerful tool that allows you to create an object of a class which requires multiple dependencies. It setups the dependencies with dummy mocks automatically, and allows you to manually setup only the ones you need in a particular test. Say you need to create a mock for UnitOfWork which takes 10 repositories as dependencies. In your test you only need to setup one of them. Autofixture allows you to create that UnitOfWork, setup that one particular repository mock (or more if you need). The rest of the dependencies will be set up automatically with dummy mocks. This saves you a huge amount of useless code. It is a little bit like an IOC container for your test.
It can also generate fake objects with random data for you. So e.q. the whole initialization of EntityModel.Document would be just one line
var repoResult = _fixture.Create<EntityModel.Document>();
Especially take a look at:
Create
Freeze
AutoMockCustomization
Here you will find my answer explaining how to use AutoFixture.
SemanticComparison Tutorial This is what will help you to avoid multiple assertions while comparing properties of objects of different types. If the properties have the same names it will to it almost automatically. If not, you can define the mappings. It will also tell you exactly which properties do not match and show their values.
Fluent assertions This just provides you a nicer way to assert stuff.
Instead of
Assert.AreEqual(repoResult.Message, savedDocument.Message);
You can do
repoResult.Message.Should().Be(savedDocument.Message);
To sum up. These tools will help you create your test with much less code and will make them much more readable. It takes time to get to know them well. Especially AutoFixture, but when you do, they become first things you add to your test projects - believe me :). Btw, they are all available from Nuget.
One more tip. If you have problems with testing a class it usually indicates a bad architecture. The solution usually is to extract smaller classes from the problematic class. (Single Responsibility Principal) Than you can easily test the small classes for business logic. And easily test the original class for interactions with them.
Consider using anonymous types:
public void Save_ReturnSavedDocument()
{
// (unmodified code)...
//Assert that properties are correctly mapped after save
Assert.AreEqual(
new
{
repoResult.Message,
repoResult.DocumentId,
repoResult.Name,
repoResult.Email,
repoResult.Comment,
},
new
{
savedDocument.Message,
savedDocument.DocumentId,
savedDocument.Name,
savedDocument.Email,
savedDocument.Comment,
});
}
There is one thing to look-out for: nullable types (eg. int?) and properties that might have slightly different types (float vs double) - but you can workaround this by casting properties to specific types (eg. (int?)repoResult.DocumentId ).
Another option would be to create a custom assert class/method(s).
Basically, the trick is to push as much clutter as you can outside of the unittests, so that only the behaviour
that is to be tested remains.
Some ways to do that:
Don't declare instances of your model/poco classes inside each test, but rather use a static TestData class that
exposes these instances as properties. Usually these instances are useful for more than one test as well.
For added robustness, have the properties on the TestData class create and return a new object instance every time
they're accessed, so that one unittest cannot affect the next by modifying the testdata.
On your testclass, declare a helper method that accepts the (usually mocked) repositories and returns the
system-under-test (or "SUT", i.e. your service). This is mainly useful in situations where configuring the SUT
takes more than 2 or more statements, since it tidies up your test code.
As an alternative to 2, have your testclass expose properties for each of the mocked Repositories, so that you don't need to declare these in your unittests; you can even pre-initialize them with a default behaviour to reduce the configuration per unittest even further.
The helper method that returns the SUT then doesn't take the mocked Repositories as arguments, but rather contstructs the SUT using the properties. You might want to reinitialize each Repository property on each [TestInitialize].
To reduce the clutter for comparing each property of your Poco with the corresponding property on the Model object, declare a helper method on your test class that does this for you (i.e. void AssertPocoEqualsModel(Poco p, Model m)). Again, this removes some clutter and you get the reusability for free.
Or, as an alternative to 4, don't compare all properties in every unittest, but rather test the mapping code in only one place with a separate set of unittests. This has the added benefit that, should the mapping ever include new properties or change
in any other way, you don't have to update 100-odd unittests.
When not testing the property mappings, you should just verify that the SUT returns the correct object instances (i.e. based on Id or Name), and that just the properties that might be changed (by the business logic being currently tested)
contain the correct values (such as Order total).
Personally, I prefer 5 because of its maintainability, but this isn't always possible and then 4 is usually a viable alternative.
Your test code would then look like this (unverified, just for demonstration purposes):
[TestClass]
public class DocumentServiceTest
{
private IDocumentRepository DocumentRepositoryMock { get; set; }
[TestInitialize]
public void Initialize()
{
DocumentRepositoryMock = MockRepository.GenerateStub<IDocumentRepository>();
}
[TestMethod]
public void Save_ReturnSavedDocument()
{
//Arrange
var repoResult = TestData.AcmeDocumentEntity;
DocumentRepositoryMock
.Stub(m => m.Get())
.IgnoreArguments()
.Return(new List<EntityModel.Document>() { repoResult }.AsQueryable());
DocumentRepositoryMock
.Stub(a => a.Save(null, null))
.IgnoreArguments()
.Return(repoResult);
//Act
var documentService = CreateDocumentService();
var savedDocument = documentService.Save(TestData.AcmeDocumentModel);
//Assert that properties are correctly mapped after save
AssertEntityEqualsModel(repoResult, savedDocument);
}
//Helpers
private DocumentService CreateDocumentService()
{
return new DocumentService(DocumentRepositoryMock);
}
private void AssertEntityEqualsModel(EntityModel.Document entityDoc, Models.Document modelDoc)
{
Assert.AreEqual(entityDoc.Message, modelDoc.Message);
Assert.AreEqual(entityDoc.DocumentId, modelDoc.DocumentId);
//...
}
}
public static class TestData
{
public static EntityModel.Document AcmeDocumentEntity
{
get
{
//Note that a new instance is returned on each invocation:
return new EntityModel.Document()
{
DocumentId = 2,
Message = "TestMessage1",
//...
}
};
}
public static Models.Document AcmeDocumentModel
{
get { /* etc. */ }
}
}
In general, if your having a hard time creating a concise test, your testing the wrong thing or the code your testing has to many responsibilities. (In my experience)
In specific, it looks like your testing the wrong thing here. If your repo is using entity framework, your getting the same object back that your sending in. Ef just updates to Id for new objects and any time stamp fields you might have.
Also, if you can't get one of your asserts to fail without a second assert failing, then you don't need one of them. Is it really possible for "name" to come back ok but for "email" to fail? If so, they should be in separate tests.
Finally, trying to do some tdd might help. Comment out all the could in your service.save. Then, write a test that fails. Then un comment out only enough code to make your test pass. Them write your next failing test. Can't write a test that fails? Then your done.

Should you have duplicate unit tests for seperate methods that share the same private implementation?

I am building a business layer for our large enterprise application, and we're currently sitting at just under 500 unit tests. The scenario is that we have two public methods, public AddT(T) and public UpdateT(T) that both make an internal call to private AddOrUpdateT(T) since a lot of the core logic is the same between both, but not all; they are different.
Because they are separate public API (regardless of private implementation), I wrote unit tests for each API, even though they are the same. This might look like
[TestMethod]
public void AddT_HasBehaviorA()
{
}
[TestMethod]
public void UpdateT_HasBehaviorA()
{
}
Currently for this particular business object there are around 30 unit tests for adding, and 40 unit tests for updating, where 30 of the update tests are the same as the add tests.
Is this normal, or should I be abstracting the common behavior out into a public helper class that is unit tested in isolation, and the two API's just use that helper class instead of a private method that has the implementation?
What is considered a best practice for these situations?
First of all, it's important to understand why you want to cover those methods by unit tests, because that's going to influence the answer. Only you and your team knows this, but if we assume that at least part of the motivation for unit testing is to get a trustworthy regression test suite, you should test the observable behaviour of the System Under Test (SUT).
In other words, unit tests should be black box tests. The tests shouldn't know about the implementation details of the SUT. Thus, the naive conclusion you could draw from this is that if you have duplicate behaviour, you should also have duplicate test code.
However, the more complex your system becomes, and the more it relies on common behaviour and strategies, the harder it becomes to implement this testing strategy. This is because you'll have a combinatorial explosion of possible ways through the system. J.B. Rainsberger explains it better than I do.
A better alternative is often to listen to your tests (a concept popularized by GOOS). In this case, it sounds like it would be valuable to extract the common behaviour into a public method. This, however, doesn't itself solve the problem of combinatorial explosion. While you can now test the common behaviour in isolation, you also need to prove that the two original methods (Add and Update) use the new public method (instead of, e.g., some copy-and-pasted code).
The best way to do that is to compose the methods with the new Strategy:
public class Host<T>
{
private readonly IHelper<T> helper;
public Host(IHelper<T> helper)
{
this.helper = helper;
}
public void Add(T item)
{
// Do something
this.helper.AddOrUpdate(item);
// Do something else
}
public void Update(T item)
{
// Do something
this.helper.AddOrUpdate(item);
// Do something else
}
}
(Obviously, you'll need to give the types and methods better names.)
This enables you to use Behaviour Verification to prove that the Add and Update methods correctly use the AddOrUpdate method:
[TestMethod]
public void AddT_HasBehaviorA()
{
var mock = new Mock<IHelper<object>>();
var sut = new Host<object>(mock.Object);
var item = new object();
sut.Add(item);
mock.Verify(h => h.AddOrUpdate(item));
}
[TestMethod]
public void UpdateT_HasBehaviorA()
{
var mock = new Mock<IHelper<object>>();
var sut = new Host<object>(mock.Object);
var item = new object();
sut.Update(item);
mock.Verify(h => h.AddOrUpdate(item));
}
It is a good practice to avoid duplication as much as possible. This aids code readability and maintainability (and probably other *ablilities ;-)). It also makes testing easier as you can start to test the common functionality in one place and not have to have so many duplicate tests. Also, duplication in tests is bad as well.
Another best practice is to only write unit tests for functionality that has unique logic. If in your Add and Update methods, you are only calling another method, there is no need to write unit tests at that level, you should be focusing on the called method.
Which brings up back to the initial point of not duplicating code and if you have private methods that share duplicate code, it may be a good idea to break it out into something else that you can run tests against.
"Since a lot of the core logic is the same between both, but not all; they are different."
I think you should have separate unit tests for these, because as you say they are not exactly the same. Also, what if you later change the implementation to call two different methods? Then your unit tests will only be testing one of them because they are coupled to the implementation detail of the two methods. The tests will pass, but you may have introduced a bug.
I think a better approach is to test both methods but add helper methods/classes to do the common work.

Unit testing using two functions

I've neglected unit testing for some time. I wrote unit tests, but they were fairly poor.
I'm now reading through "The art of unit Testing" to bring myself up to scratch.
If I have an interface such as:
public interface INotificationService
{
void AddError(string _error);
void AddIssue(string _issue);
IEnumerable<string> FetchErrors();
IEnumerable<string> FetchIssues();
}
A concrete implementation of this interface contains:
private readonly ICollection<Message> messages;
Adding an error or issue creates a new message with an enum denoting it's type and adds it to the collection.
Calling FetchErrors() / FetchIssues() returns messages of that type from the collection.
Would the following test be valid?:
[Test]
public void FetchErrors_LoggingEnabledAddErrorFetchErrors_ReturnsError()
{
notificationService = new NotificationService();
notificationService.AddError("A new error");
Assert.AreEqual(new []{"A new error"}, notificationService.FetchErrors());
}
My concern is that I'm first calling AddError(), then testing the result of FetchErrors(). So I'm calling two functions. Is this incorrect?
Should I make the collection public and directly assert that it contains a message of the appropriate type containing the logged error message?
What would be the best practice in this scenario?
Your approach looks OK - testing the implementation through the public methods is the only access made available in the design.
In order to test the methods independently of one another, you would need to use a white-box testing backdoor like reflection to access the private messages to ensure that the respective Add* methods work. This isn't a good idea at all, since your tests will break (at run time) every time the underlying CUT implementation changes.
A common, better alternative to reflection is to expose a non-interface internal method on the concrete class under test which allowed you some kind of 'maintenance hatch' access to the ICollection<Message> messages; implementation field, and then allow InternalsVisibleTo access to the Unit test assembly.
One note - you'll find that Assert.AreEqual on an the string enumerable will do a reference comparison and thus fail (because you are comparing it to a new array).
You'll probably have to change this to something like:
Assert.IsTrue(notificationService.FetchErrors().Contains("A new error"));
Edit
IMO you don't need to go as far as making the field public in .Net. Since you have the interface abstraction in place already which should in theory restrict the means of access to the CUT, it is quite common to use internal scope and InternalsVisibleTo to allow the UT special access. Jon Skeet et al have mentioned this here
#region Unit Testing side-door
internal ICollection<Message> Messages
{
get { return _messages };
// No Setter
}
#endregion
Your approach is perfectly ok. A unit test should follow the Arrange-Act-Assert structure - and your call to notificationService.AddError(..) simply is part of the test's Arrange section.
It's not that you cannot call more than one method in a test (in many cases you will have to), the point is that you should only assert/test for one single fact. That's what you do, so everything looks good.
As others pointed out, it's OK to use both methods. You are testing the behavior of the class, and it is that whenever an error is published, you can read it.
If the implementation is more complicated, then probably you may need to rethink the design, as your method(s) do too much. Looking at what you describe, why actually you need the getter to be a method?
In general, I do not like the idea of exposing internal method only for testing purposes. This send a wrong message to whoever is going to maintain that code in the future (even you, after you forget). It says - yeah, go ahead, access this collection directly from any class in this assembly.
We can't say if your test is valid or not based on the code you posted. We don't know what AddError() does so is not possible to know if the unit test is correct.
If AddError just add an error into the collection and do anything else then your test is good and call FetchErrors() is valid because it has to have a separated unit test which verifies it. In any case if your AddError method does anything else you have to change the test and verify all the steps that method does.

Making a private method public to unit test it...good idea?

Moderator Note: There are already 39 answers posted here (some have been deleted). Before you post your answer, consider whether or not you can add something meaningful to the discussion. You're more than likely just repeating what someone else has already said.
I occasionally find myself needing to make a private method in a class public just to write some unit tests for it.
Usually this would be because the method contains logic shared between other methods in the class and it's tidier to test the logic on its own, or another reason could be possible be I want to test logic used in synchronous threads without having to worry about threading problems.
Do other people find themselves doing this, because I don't really like doing it?? I personally think the bonuses outweigh the problems of making a method public which doesn't really provide any service outside of the class...
UPDATE
Thanks for answers everyone, seems to have piqued peoples' interest. I think the general consensus is testing should happen via the public API as this is the only way a class will ever be used, and I do agree with this. The couple of cases I mentioned above where I would do this above were uncommon cases and I thought the benefits of doing it was worth it.
I can however, see everyones point that it should never really happen. And when thinking about it a bit more I think changing your code to accommodate tests is a bad idea - after all I suppose testing is a support tool in a way and changing a system to 'support a support tool' if you will, is blatant bad practice.
Note:
This answer was originally posted for the question Is unit testing alone ever a good reason to expose private instance variables via getters? which was merged into this one, so it may be a tad specific to the usecase presented there.
As a general statement, I'm usually all for refactoring "production" code to make it easier to test. However, I don't think that would be a good call here. A good unit test (usually) shouldn't care about the class' implementation details, only about its visible behavior. Instead of exposing the internal stacks to the test, you could test that the class returns the pages in the order you expect it to after calling first() or last().
For example, consider this pseudo-code:
public class NavigationTest {
private Navigation nav;
#Before
public void setUp() {
// Set up nav so the order is page1->page2->page3 and
// we've moved back to page2
nav = ...;
}
#Test
public void testFirst() {
nav.first();
assertEquals("page1", nav.getPage());
nav.next();
assertEquals("page2", nav.getPage());
nav.next();
assertEquals("page3", nav.getPage());
}
#Test
public void testLast() {
nav.last();
assertEquals("page3", nav.getPage());
nav.previous();
assertEquals("page2", nav.getPage());
nav.previous();
assertEquals("page1", nav.getPage());
}
}
Personally, I'd rather unit test using the public API and I'd certainly never make the private method public just to make it easy to test.
If you really want to test the private method in isolation, in Java you could use Easymock / Powermock to allow you to do this.
You have to be pragmatic about it and you should also be aware of the reasons why things are difficult to test.
'Listen to the tests' - if it's difficult to test, is that telling you something about your design? Could you refactor to where a test for this method would be trivial and easily covered by testing through the public api?
Here's what Michael Feathers has to say in 'Working Effectively With Legacy Code"
"Many people spend a lot of time trying ot figure out how to get around this problem ... the real answer is that if you have the urge to test a private method, the method shouldn't be private; if making the method public bothers you, chances are, it is because it is part of a separate reponsibility; it should be on another class." [Working Effectively With Legacy Code (2005) by M. Feathers]
As others have said, it is somewhat suspect to be unit testing private methods at all; unit test the public interface, not the private implementation details.
That said, the technique I use when I want to unit test something that is private in C# is to downgrade the accessibility protection from private to internal, and then mark the unit testing assembly as a friend assembly using InternalsVisibleTo. The unit testing assembly will then be allowed to treat the internals as public, but you don't have to worry about accidentally adding to your public surface area.
Lots of answers suggest only testing the public interface, but IMHO this is unrealistic - if a method does something that takes 5 steps, you'll want to test those five steps separately, not all together. This requires testing all five methods, which (other than for testing) might otherwise be private.
The usual way of testing "private" methods is to give every class its own interface, and make the "private" methods public, but not include them in the interface. This way, they can still be tested, but they don't bloat the interface.
Yes, this will result in file- and class-bloat.
Yes, this does make the public and private specifiers redundant.
Yes, this is a pain in the ass.
This is, unfortunately, one of the many sacrifices we make to make code testable. Perhaps a future language (or a even a future version of C#/Java) will have features to make class- and module-testability more convenient; but in the meanwhile, we have to jump through these hoops.
There are some who would argue that each of those steps should be its own class, but I disagree - if they all share state, there is no reason to create five separate classes where five methods would do. Even worse, this results in file- and class-bloat. Plus, it infects the public API of your module - all those classes must necessarily be public if you want to test them from another module (either that, or include the test code in the same module, which means shipping the test code with your product).
A unit test should test the public contract, the only way how a class could be used in other parts of the code. A private method is implementation details, you should not test it; as far as public API works correctly, the implementation doesn't matter and could be changed without changes in test cases.
IMO, you should write your tests not making deep assumptions on how your class implemented inside. You probably want to refactor it later using another internal model but still making the same guarantees that previous implementation gives.
Keeping that in mind I suggest you to focus on testing that your contract is still holds no matter what internal implementation your class currently have. Property based testing of your public APIs.
How about making it package private? Then your test code can see it (and other classes in your package as well), but it is still hidden from your users.
But really, you should not be testing private methods. Those are implementation details, and not part of the contract. Everything they do should be covered by calling the public methods (if they have code in there that is not exercised by the public methods, then that should go). If the private code is too complex, the class is probably doing too many things and in want of refactoring.
Making a method public is big commitment. Once you do that, people will be able to use it, and you cannot just change them anymore.
Update: I have added a more expanded and more complete answer to this question in numerous other places. This is can be found on my blog.
If I ever need to make something public to test it, this usually hints that the system under test is not following the Single Reponsibility Principle. Hence there is a missing class that should be introduced. After extracting the code into a new class, make it public. Now you can test easily, and you are following SRP. Your other class simply has to invoke this new class via composition.
Making methods public/using langauge tricks such as marking code as visible to test assembilies should always be a last resort.
For example:
public class SystemUnderTest
{
public void DoStuff()
{
// Blah
// Call Validate()
}
private void Validate()
{
// Several lines of complex code...
}
}
Refactor this by introducing a validator object.
public class SystemUnderTest
{
public void DoStuff()
{
// Blah
validator.Invoke(..)
}
}
Now all we have to do is test that the validator is invoked correctly. The actual process of validation (the previously private logic) can be tested in pure isolation. There will be no need for complex test set up to ensure this validation passes.
Some great answers. One thing I didn't see mentioned is that with test-driven development (TDD), private methods are created during the refactoring phase (look at Extract Method for an example of a refactoring pattern), and should therefore already have the necessary test coverage. If done correctly (and of course, you're going to get a mixed bag of opinions when it comes to correctness), you shouldn't have to worry about having to make a private method public just so that you can test it.
If you are using C# you can make method internal. That way you don't pollute public API.
Then add attribute to dll
[assembly: InternalsVisibleTo("MyTestAssembly")]
Now all the methods are visible in your MyTestAssembly project. Maybe not perfect, but better then making private method public just to test it.
Why not split out the stack management algorithm into a utility class? The utility class can manage the stacks and provide public accessors. Its unit tests can be focussed on implementation detail. Deep tests for algorithmically tricky classes are very helpful in wrinkling out edge cases and ensuring coverage.
Then your current class can cleanly delegate to the utility class without exposing any implementation details. Its tests will relate to the pagination requirement as others have recommended.
In java, there's also the option of making it package private (ie leaving off the visibility modifier). If your unit tests are in the same package as the class being tested it should then be able to see these methods, and is a bit safer than making the method completely public.
Private methods are usually used as "helper" methods. Therefore they only return basic values and never operate on specific instances of objects.
You have a couple of options if you want to test them.
Use reflection
Give the methods package access
Alternatively you could create a new class with the helper method as a public method if it is a good enough candidate for a new class.
There is a very good article here on this.
Use reflection to access the private variables if you need to.
But really, you don't care about the internal state of the class, you just want to test that the public methods return what you expect in the situations you can anticipate.
In your update you say that it's good to just test using the public API.
There is actually two schools here.
Black box testing
The black box school says that the class should be considered as a black box that no one can see the implementation inside it. The only way to test this is through the public API -- just like the user's of the class will be using it.
white box testing.
The white box school thinks it naturally to use the knowledge about the implementation of the class and then test the class to know that it works as it should.
I really cannot take side in the discussion. I just thought it would be interesting to know that there are two distinct ways to test a class (or a library or whatever).
in terms of unit testing, you should definitely not add more methods; I believe you would better make a test case just about your first() method, which would be called before each test; then you can call multiple times the - next(), previous() and last() to see if the outcomes match your expectation.
I guess if you don't add more methods to your class (just for testing purposes), you would stick to the "black box" principle of testing;
You should never ever ever let your tests dictate your code. I'm not speaking about TDD or other DDs I mean, exactly what your asking. Does your app need those methods to be public. If it does then test them. If it does not then then don't make them public just for testing. Same with variables and others. Let your application's needs dictate the code, and let your tests test that the need is met. (Again I don't mean testing first or not I mean changing a classes structure to meet a testing goal).
Instead you should "test higher". Test the method that calls the private method. But your tests should be testing your applications needs and not your "implementation decisions".
For example (bod pseudo code here);
public int books(int a) {
return add(a, 2);
}
private int add(int a, int b) {
return a+b;
}
There is no reason to test "add" you can test "books" instead.
Never ever let your tests make code design decisions for you. Test that you get the expected result, not how you get that result.
I would say it is a bad idea for I am not sure whether you get any benefit and potentially problems down the line. If you are changing the contract of a calls, just to test a private method, you're not testing the class in how it would be used, but creating an artificial scenario which you never intended to happen.
Furthermore, by declaring the method as public, what's to say that in six months time (after forgetting that the only reason for making a method public is for testing) that you (or if you've handed the project over) somebody completely different won't use it, leading to potentially unintended consequences and/or a maintenance nightmare.
First see if the method ought to be extracted into another class and made public. If that's not the case, make it package protected and in Java annotate with #VisibleForTesting.
Private methods that you want to test in isolation are an indication that there's another "concept" buried in your class. Extract that "concept" to its own class and test it as a separate "unit".
Take a look at this video for a really interesting take on the subject.
There are actually situations when you should do this (e.g. when you're implementing some complex algorithms). Just do it package-private and this will be enough.
But in most cases probably you have too complex classes which requires factoring out logic into other classes.
I tend to agree that the bonuses of having it unit tested outweigh the problems of increasing the visibility of some of the members. A slight improvement is to make it protected and virtual, then override it in a test class to expose it.
Alternatively, if it's functionality you want to test separately does it not suggest a missing object from your design? Maybe you could put it in a separate testable class...then your existing class just delegates to an instance of this new class.
I generally keep the test classes in the same project/assembly as the classes under test.
This way I only need internal visibility to make functions/classes testable.
This somewhat complicates your building process, which needs to filter out the test classes.
I achieve this by naming all my test classes TestedClassTest and using a regex to filter those classes.
This of course only applies to the C# / .NET part of your question
I will often add a method called something like validate, verify, check, etc, to a class so that it can be called to test the internal state of an object.
Sometimes this method is wrapped in an ifdef block (I write mostly in C++) so that it isn't compiled for release. But it's often useful in release to provide validation methods that walk the program's object trees checking things.
Guava has a #VisibleForTesting annotation for marking methods that have enlarged scope (package or public) that they would otherwise. I use a #Private annotation for the same thing.
While the public API must be tested, sometimes it's convenient and sensible to get at stuff that wouldn't normally be public.
When:
a class is made significantly less readable, in toto, by breaking it up into multiple classes,
just to make it more testable,
and providing some test access to the innards would do the trick
it seems like religion is trumping engineering.
I usually leave those methods as protected and place the unit test within the same package (but in another project or source folder), where they can access all the protected methods because the class loader will place them within the same namespace.
No, because there are better ways of skinning that cat.
Some unit test harnesses rely on macros in the class definition which automagically expand to create hooks when built in test mode. Very C style, but it works.
An easier OO idiom is to make anything you want to test "protected" rather than "private". The test harness inherits from the class under test, and can then access all protected members.
Or you go for the "friend" option. Personally this is the feature of C++ I like least because it breaks the encapsulation rules, but it happens to be necessary for how C++ implements some features, so hey ho.
Anyway, if you're unit testing then you're just as likely to need to inject values into those members. White box texting is perfectly valid. And that really would break your encapsulation.
In .Net there is a special class called PrivateObject deigned specifically to allow you to access private methods of a class.
See more about it on the MSDN or here on Stack Overflow
(I am wondering that no one has mentioned it so far.)
There are situations though which this is not enough, in which case you will have to use reflection.
Still I would adhere to the general recommendation not to test private methods, however as usual there are always exceptions.
Very answered question.
IHMO, the excellent answer from #BlueRaja - Danny Pflughoeft is one of the best.
Lots of answers suggest only testing the public interface, but IMHO
this is unrealistic - if a method does something that takes 5 steps,
you'll want to test those five steps separately, not all together.
This requires testing all five methods, which (other than for testing)
might otherwise be private.
Above all, I want to stress that the question "should we make a private method public to unit test it" is a question which an objectively correct answer depends on multiple parameters.
So I think that in some cases we have not to and in others we should.
Making public a private method or extracting the private method as a public method in another class (new or existing)?
It is rarely the best way.
A unit test has to test the behavior of one API method/function.
If you test a public method that invokes another public method belonging to the same component, you don't unit test the method. You test multiple public methods at the same time.
As a consequence, you may duplicate tests, test fixtures, test assertions, the test maintenance and more generally the application design.
As the tests value decreases, they often lose interest for developers that write or maintain them.
To avoid all this duplication, instead of making the private method public method, in many cases a better solution is extracting the private method as a public method in a new or an existing class.
It will not create a design defect.
It will make the code more meaningful and the class less bloat.
Besides, sometimes the private method is a routine/subset of the class while the behavior suits better in a specific structure.
At last, it also makes the code more testable and avoid tests duplication.
We can indeed prevent tests duplication by unit testing the public method in its own test class and in the test class of the client classes, we have just to mock the dependency.
Mocking private methods?
While it is possible by using reflection or with tools as PowerMock, I think that it is often a way to bypass a design issue.
A private member is not designed to be exposed to other classes.
A test class is a class as another. So we should apply the same rule for it.
Mocking public methods of the object under test?
You may want to change the modifier private to public to test the method.
Then to test the method that uses this refactored public method, you may be tempted to mock the refactored public method by using tools as Mockito (spy concept) but similarly to mocking private methods, we should avoid to mock the object under test.
The Mockito.spy() documentation says it itself :
Creates a spy of the real object. The spy calls real methods unless they are > > stubbed.
Real spies should be used carefully and occasionally, for example when
dealing with legacy code.
By experience, using spy() generally decreases the test quality and its readability.
Besides, it is much more error-prone as the object under test is both a mock and a real object.
It is often the best way to write an invalid acceptance test.
Here is a guideline I use to decide whether a private method should stay private or be refactored.
Case 1) Never make a private method public if this method is invoked once.
It is a private method for a single method. So you could never duplicate test logic as it is invoke once.
Case 2) You should wonder whether a private method should be refactored as a public method if the private method is invoked more than once.
How to decide ?
The private method doesn't produce duplication in the tests.
-> Keep the method private as it is.
The private method produces duplication in the tests. That is, you need to repeat some tests, to assert the same logic for each test that unit-tests public methods using the private method.
-> If the repeated processing may make part of the API provided to clients (no security issue, no internal processing, etc...), extract the private method as a public method in a new class.
-> Otherwise, if the repeated processing has not to make part of the API provided to clients (security issue, internal processing, etc...), don't widen the visibility of the private method to public.
You may leave it unchanged or move the method in a private package class that will never make part of the API and would be never accessible by clients.
Code examples
The examples rely on Java and the following libraries : JUnit, AssertJ (assertion matcher) and Mockito.
But I think that the overall approach is also valid for C#.
1) Example where the private method doesn't create duplication in the test code
Here is a Computation class that provides methods to perform some computations.
All public methods use the mapToInts() method.
public class Computation {
public int add(String a, String b) {
int[] ints = mapToInts(a, b);
return ints[0] + ints[1];
}
public int minus(String a, String b) {
int[] ints = mapToInts(a, b);
return ints[0] - ints[1];
}
public int multiply(String a, String b) {
int[] ints = mapToInts(a, b);
return ints[0] * ints[1];
}
private int[] mapToInts(String a, String b) {
return new int[] { Integer.parseInt(a), Integer.parseInt(b) };
}
}
Here is the test code :
public class ComputationTest {
private Computation computation = new Computation();
#Test
public void add() throws Exception {
Assert.assertEquals(7, computation.add("3", "4"));
}
#Test
public void minus() throws Exception {
Assert.assertEquals(2, computation.minus("5", "3"));
}
#Test
public void multiply() throws Exception {
Assert.assertEquals(100, computation.multiply("20", "5"));
}
}
We could see that the invocation of the private method mapToInts() doesn't duplicate the test logic.
It is an intermediary operation and it doesn't produce a specific result that we need to assert in the tests.
2) Example where the private method creates undesirable duplication in the test code
Here is a MessageService class that provides methods to create messages.
All public methods use the createHeader() method :
public class MessageService {
public Message createMessage(String message, Credentials credentials) {
Header header = createHeader(credentials, message, false);
return new Message(header, message);
}
public Message createEncryptedMessage(String message, Credentials credentials) {
Header header = createHeader(credentials, message, true);
// specific processing to encrypt
// ......
return new Message(header, message);
}
public Message createAnonymousMessage(String message) {
Header header = createHeader(Credentials.anonymous(), message, false);
return new Message(header, message);
}
private Header createHeader(Credentials credentials, String message, boolean isEncrypted) {
return new Header(credentials, message.length(), LocalDate.now(), isEncrypted);
}
}
Here is the test code :
import java.time.LocalDate;
import org.assertj.core.api.Assertions;
import org.junit.Test;
import junit.framework.Assert;
public class MessageServiceTest {
private MessageService messageService = new MessageService();
#Test
public void createMessage() throws Exception {
final String inputMessage = "simple message";
final Credentials inputCredentials = new Credentials("user", "pass");
Message actualMessage = messageService.createMessage(inputMessage, inputCredentials);
// assertion
Assert.assertEquals(inputMessage, actualMessage.getMessage());
Assertions.assertThat(actualMessage.getHeader())
.extracting(Header::getCredentials, Header::getLength, Header::getDate, Header::isEncryptedMessage)
.containsExactly(inputCredentials, 9, LocalDate.now(), false);
}
#Test
public void createEncryptedMessage() throws Exception {
final String inputMessage = "encryted message";
final Credentials inputCredentials = new Credentials("user", "pass");
Message actualMessage = messageService.createEncryptedMessage(inputMessage, inputCredentials);
// assertion
Assert.assertEquals("AƧ4B36ddflm1Dkok49d1d9gaz", actualMessage.getMessage());
Assertions.assertThat(actualMessage.getHeader())
.extracting(Header::getCredentials, Header::getLength, Header::getDate, Header::isEncryptedMessage)
.containsExactly(inputCredentials, 9, LocalDate.now(), true);
}
#Test
public void createAnonymousMessage() throws Exception {
final String inputMessage = "anonymous message";
Message actualMessage = messageService.createAnonymousMessage(inputMessage);
// assertion
Assert.assertEquals(inputMessage, actualMessage.getMessage());
Assertions.assertThat(actualMessage.getHeader())
.extracting(Header::getCredentials, Header::getLength, Header::getDate, Header::isEncryptedMessage)
.containsExactly(Credentials.anonymous(), 9, LocalDate.now(), false);
}
}
We could see that the invocation of the private method createHeader() creates some duplication in the test logic.
createHeader() creates indeed a specific result that we need to assert in the tests.
We assert 3 times the header content while a single assertion should be required.
We could also note that the asserting duplication is close between the methods but not necessary the same as the private method has a specific logic :
Of course, we could have more differences according to the logic complexity of the private method.
Besides, at each time we add a new public method in MessageService that calls createHeader(), we will have to add this assertion.
Note also that if createHeader() modifies its behavior, all these tests may also need to be modified.
Definitively, it is not a very good design.
Refactoring step
Suppose we are in a case where createHeader() is acceptable to make part of the API.
We will start by refactoring the MessageService class by changing the access modifier of createHeader() to public :
public Header createHeader(Credentials credentials, String message, boolean isEncrypted) {
return new Header(credentials, message.length(), LocalDate.now(), isEncrypted);
}
We could now test unitary this method :
#Test
public void createHeader_with_encrypted_message() throws Exception {
...
boolean isEncrypted = true;
// action
Header actualHeader = messageService.createHeader(credentials, message, isEncrypted);
// assertion
Assertions.assertThat(actualHeader)
.extracting(Header::getCredentials, Header::getLength, Header::getDate, Header::isEncryptedMessage)
.containsExactly(Credentials.anonymous(), 9, LocalDate.now(), true);
}
#Test
public void createHeader_with_not_encrypted_message() throws Exception {
...
boolean isEncrypted = false;
// action
messageService.createHeader(credentials, message, isEncrypted);
// assertion
Assertions.assertThat(actualHeader)
.extracting(Header::getCredentials, Header::getLength, Header::getDate, Header::isEncryptedMessage)
.containsExactly(Credentials.anonymous(), 9, LocalDate.now(), false);
}
But what about the tests we write previously for public methods of the class that use createHeader() ?
Not many differences.
In fact, we are still annoyed as these public methods still need to be tested concerning the returned header value.
If we remove these assertions, we may not detect regressions about it.
We should be able to naturally isolate this processing but we cannot as the createHeader() method belongs to the tested component.
That's why I explained at the beginning of my answer that in most of cases, we should favor the extraction of the private method in another class to the change of the access modifier to public.
So we introduce HeaderService :
public class HeaderService {
public Header createHeader(Credentials credentials, String message, boolean isEncrypted) {
return new Header(credentials, message.length(), LocalDate.now(), isEncrypted);
}
}
And we migrate the createHeader() tests in HeaderServiceTest.
Now MessageService is defined with a HeaderService dependency:
public class MessageService {
private HeaderService headerService;
public MessageService(HeaderService headerService) {
this.headerService = headerService;
}
public Message createMessage(String message, Credentials credentials) {
Header header = headerService.createHeader(credentials, message, false);
return new Message(header, message);
}
public Message createEncryptedMessage(String message, Credentials credentials) {
Header header = headerService.createHeader(credentials, message, true);
// specific processing to encrypt
// ......
return new Message(header, message);
}
public Message createAnonymousMessage(String message) {
Header header = headerService.createHeader(Credentials.anonymous(), message, false);
return new Message(header, message);
}
}
And in MessageService tests, we don't need any longer to assert each header value as this is already tested.
We want to just ensure that Message.getHeader() returns what HeaderService.createHeader() has returned.
For example, here is the new version of createMessage() test :
#Test
public void createMessage() throws Exception {
final String inputMessage = "simple message";
final Credentials inputCredentials = new Credentials("user", "pass");
final Header fakeHeaderForMock = createFakeHeader();
Mockito.when(headerService.createHeader(inputCredentials, inputMessage, false))
.thenReturn(fakeHeaderForMock);
// action
Message actualMessage = messageService.createMessage(inputMessage, inputCredentials);
// assertion
Assert.assertEquals(inputMessage, actualMessage.getMessage());
Assert.assertSame(fakeHeaderForMock, actualMessage.getHeader());
}
Note the assertSame() use to compare the object references for the headers and not the contents.
Now, HeaderService.createHeader() may change its behavior and return different values, it doesn't matter from the MessageService tests point of view.
The point of the unit test is to confirm the workings of the public api for that unit. There should be no need to make a private method exposed only for testing, if so then your interface should be rethought. Private methods can be thought as 'helper' methods to the public interface and therefore are tested via the public interface as they would be calling into the private methods.
The only reason I can see that you have a 'need' to do this is that your class is not properly designed for testing in mind.

Unit testing and checking private variable value

I am writing unit tests with C#, NUnit and Rhino Mocks.
Here are the relevant parts of a class I am testing:
public class ClassToBeTested
{
private IList<object> insertItems = new List<object>();
public bool OnSave(object entity, object id)
{
var auditable = entity as IAuditable;
if (auditable != null) insertItems.Add(entity);
return false;
}
}
I want to test the values in insertItems after a call to OnSave:
[Test]
public void OnSave_Adds_Object_To_InsertItems_Array()
{
Setup();
myClassToBeTested.OnSave(auditableObject, null);
// Check auditableObject has been added to insertItems array
}
What is the best practice for this? I have considered adding insertItems as a Property with a public get, or injecting a List into ClassToBeTested, but not sure I should be modifying the code for purposes of testing.
I have read many posts on testing private methods and refactoring, but this is such a simple class I wondered what is the best option.
The quick answer is that you should never, ever access non-public members from your unit tests. It totally defies the purpose of having a test suite, since it locks you into internal implementation details that you may not want to keep that way.
The longer answer relates to what to do then? In this case, it is important to understand why the implementation is as it is (this is why TDD is so powerful, because we use the tests to specify the expected behavior, but I get the feeling that you are not using TDD).
In your case, the first question that comes to mind is: "Why are the IAuditable objects added to the internal list?" or, put differently, "What is the expected externally visible outcome of this implementation?" Depending on the answer to those questions, that's what you need to test.
If you add the IAuditable objects to your internal list because you later want to write them to an audit log (just a wild guess), then invoke the method that writes the log and verify that the expected data was written.
If you add the IAuditable object to your internal list because you want to amass evidence against some kind of later Constraint, then try to test that.
If you added the code for no measurable reason, then delete it again :)
The important part is that it is very beneficial to test behavior instead of implementation. It is also a more robust and maintainable form of testing.
Don't be afraid to modify your System Under Test (SUT) to be more testable. As long as your additions make sense in your domain and follow object-oriented best practices, there are no problems - you would just be following the Open/Closed Principle.
You shouldn't be checking the list where the item was added. If you do that, you'll be writing a unit test for the Add method on the list, and not a test for your code. Just check the return value of OnSave; that's really all you want to test.
If you're really concerned about the Add, mock it out of the equation.
Edit:
#TonE: After reading your comments I'd say you may want to change your current OnSave method to let you know about failures. You may choose to throw an exception if the cast fails, etc. You could then write a unit test that expects and exception, and one that doesn't.
I would say the "best practice" is to test something of significance with the object that is different now that it stored the entity in the list.
In other words, what behavior is different about the class now that it stored it, and test for that behavior. The storage is an implementation detail.
That being said, it isn't always possible to do that.
You can use reflection if you must.
If I'm not mistaken, what you really want to test is that it only adds items to the list when they can be cast to IAuditable. So, you might write a few tests with method names like:
NotIAuditableIsNotSaved
IAuditableInstanceIsSaved
IAuditableSubclassInstanceIsSaved
... and so forth.
The problem is that, as you note, given the code in your question, you can only do this by indirection - only by checking the private insertItems IList<object> member (by reflection or by adding a property for the sole purpose of testing) or injecting the list into the class:
public class ClassToBeTested
{
private IList _InsertItems = null;
public ClassToBeTested(IList insertItems) {
_InsertItems = insertItems;
}
}
Then, it's simple to test:
[Test]
public void OnSave_Adds_Object_To_InsertItems_Array()
{
Setup();
List<object> testList = new List<object>();
myClassToBeTested = new MyClassToBeTested(testList);
// ... create audiableObject here, etc.
myClassToBeTested.OnSave(auditableObject, null);
// Check auditableObject has been added to testList
}
Injection is the most forward looking and unobtrusive solution unless you have some reason to think the list would be a valuable part of your public interface (in which case adding a property might be superior - and of course property injection is perfectly legit too). You could even retain a no-argument constructor that provides a default implementation (new List()).
It is indeed a good practice; It might strike you as a bit overengineered, given that it's a simple class, but the testability alone is worth it. Then on top of that, if you find another place you want to use the class, that will be icing on the cake, since you won't be limited to using an IList (not that it would take much effort to make the change later).
If the list is an internal implementation detail (and it seems to be), then you shouldn't test it.
A good question is, what is the behavior that would be expected if the item was added to the list? This may require another method to trigger it.
public void TestMyClass()
{
MyClass c = new MyClass();
MyOtherClass other = new MyOtherClass();
c.Save(other);
var result = c.Retrieve();
Assert.IsTrue(result.Contains(other));
}
In this case, i'm asserting that the correct, externally visible behavior, is that after saving the object, it will be included in the retrieved collection.
If the result is that, in the future, the passed-in object should have a call made to it in certain circumstances, then you might have something like this (please forgive pseudo-API):
public void TestMyClass()
{
MyClass c = new MyClass();
IThing other = GetMock();
c.Save(other);
c.DoSomething();
other.AssertWasCalled(o => o.SomeMethod());
}
In both cases, you're testing the externally visible behavior of the class, not the internal implementation.
The number of tests you need is dependent on the complexity of the code - how many decision points are there, roughly. Different algorithms can achieve the same result with different complexity in their implementation. How do you write a test that is independent of the implementation and still be sure you have adequate coverage of your decision points?
Now, if you are designing larger tests, at say the integration level, then, no, you would not want to write to implementation or test private methods, but the question was directed to the small, unit test scope.

Categories