The internet is flooded with pages saying that we should not write unit test cases for a private method. But I am not sure is it correct to say that we should completely ignore the private methods for unit test cases? I know they would be eventually tested if we test the main public method. But imagine my method which hits the database and populates the object from the dataset is contained, in a private method. If I want to use mock for my database I would have to write a unit test case for this method which would force me to make it public. How do I overcome such situations?
Since below is my public method if I write a unit test case for that it would hit the databse everytime. Which i want to avoid, because database is an external dependency which I always want to mock. The other problem with using DB is suppose I am hardcoding a sysid from my unit test case it would work till the time the sysid exists in db. When that record is deleted from db the test case becomes useless.
public Order RetrieveOrderAndOrderItem()
{
DataSet ordersDS = new DataSet();
Order obj = new Order();
OrdersDb.RetrieveOrders(conKey,companySysId,userSysId,orderId,ordersDS);
obj = populateObjFromDb(ordersDS,orderItemId, orderItemSubType);
return obj;
}
private Order populateObjFromDb(DataSet orders,int orderItemId, int orderItemSubType)
{
Order orderObj = new Order();
orderObj.OrderId = Converters.DBInt(orders.Tables[0].Rows[0]["OrderId"]);
return orderObj;
}
Testing private methods depends too much on the implementation of the class. You are right in stating that you test a class through its public methods. If you have a private method that does a lot of work you should move it to its own class.
When you find yourself in a situation where you want to test a private method you should start thinking about your design.
In your example, why isn't the code that reads the database and populates your objects a separate class? The Single Responsibility principle states that a class should have only one single responsibility. This new class could be injected into the original class, hereby following the Dependency Inversion principle.
The goal of things like TDD and Unit Testing is to arrive at a solution that follows the SOLID principles.
Related
I don't have a lot of experience with unit testing. For example I have simple method in the application:
public void GetName()
{
UserRights rights = new UserRights(new DatabaseContext());
string test = rights.LookupNameByID("12345");
Console.WriteLine(test);
}
In this case I'm able to test all methods of UserRights class by passing mocked DatabaseContext, but how can I test GetName() method? What is the best practice? Where DatabaseContext should be created?
If you want to test the GetName method in a properly isolated way (i.e. a Unit Test) then you can't use new to create the UserRights instance in the method itself; because a test is really just another client of the code, therefore it can't (and shouldn't) know anything about how GetName works internally
So what this means is that for a proper Unit Test you must be able to replace all dependencies of a method with ones that the client fully controls - in the case, the code in the Unit Test is the client.
In your posted code, the client code has no control at all over UserRights nor DatabaseContext, so this is the first thing that has to change.
You need to rework your code so that the UserRights implementation can be supplied by the client. In fact once that's done, the problem about where DatabaseContext comes from is actually irrelevant for the Unit test because it doesn't care about how UserRights itself performs its tasks!
There are a number of ways of doing this; you can use Mocks or Stubs, you can use Constructor or Method injection, you could use a UserRights factory. Here is an example of using very simple stubs which IMHO is the best way to start and avoids having to learn a Mocking framework -- I personally would use Mocks for this but that's cos I am lazy :)
(code below assumes the class containing GetName is called "UserService", and uses xUnit framework; but MSTest will work just fine too)
Let's suppose you have control over the code of UserService so you can make the LookupNameByID method virtual (if you can't, then you may have to go the route if interfaces and mocks)
public class UserRights
{
public virtual LookupNameByID(string id)
{
//does whatever a UserRights does.
}
}
public class UserService
{
readonly UserRights _rights;
public UserService(UserRights rights)
{
_rights=rights; //null guard omitted for brevity
}
public string GetName(string id)
{
return _rights.LookupNameByID(id);
}
}
now in your unit test code suppose you create a sub-class of UserRights like this:
public class ExplodingUserRights: UserRights
{
public override string LookupNameByID(string id)
{
throw new Exception("BOOM!");
}
}
Now you can write a test to see how GetName reacts when something bad happens:
[Fact]
public void LookupNameByID_WhenUserRightsThrowsException_DoesNotReThrow()
{
//this test will fail if an exception is thrown, thus proving that GetName doesn't handle exceptions correctly.
var sut = new UserService(new ExplodingUserRights()); <-Look, no DatabaseContext!
sut.GetName("12345");
}
and one for when good things happen:
public class HappyUserRights: UserRights
{
public override string LookupNameByID(string id)
{
return "yay!";
}
}
[Fact]
public void LookupNameByID_ReturnsResultOfUserRightsCall()
{
//this test will fail if an exception is thrown, thus proving that GetName doesn't handle exceptions correctly.
var sut = new UserService(new HappyUserRights());
var actual = sut.GetName("12345");
Assert.Equal("yay!",actual);
}
and so on. Note that we never went anywhere near DatabaseContext, because that's a problem you only have to solve when you unit test the UserRights class itself. (and at that point I would probably recommend using Jeroen's advice from his linked article,and do an integration test, unless setup of a database for each test is something you can't or won't do, in which case you need to use interfaces and mocks)
Hope that helps.
Separating your codes reliance on DB Context is something you will want to investigate, this can be accomplished using the Repository pattern. Since you're passing the DB Context into your objects constructor, in this case UserRights, you can pretty easily change your code to take in an Interface (or simply add an overloaded contructor to the class that accepts an interface, then call that in your unit tests, preserving any existing code). There are lots of ways to get this done, a quick Google search yielded the following article:
http://romiller.com/2012/02/14/testing-with-a-fake-dbcontext/
http://www.codeproject.com/Articles/207820/The-Repository-Pattern-with-EF-code-first-Dependen
Once your class can accept an interface rather than (or as an alternative to) the strongly typed DB Context object you can use a Mock framework to assist with testing. Take a look at Moq for examples on how to use these in your unit tests https://github.com/Moq/moq4/wiki/Quickstart
Be Aware: Moq can become difficult to work with when your tests require data that is related via foreign keys, the syntax can be complicated to get your head around. One thing to watch out for is the temptation to make changes to your code just to make a unit test easier to set up, while there may be value in making this change it also may indicate that you need to re-think your unit test rather than violate your applications architecture and/or design patterns
I have a Lin2Sql DataContext that I am using to get all my data from a sql database however I am struggling to find a way to successfully Mock this so that I can create relevant Unit Tests.
In my data access objects that I am wanting to test I am refreshing the context each time and I am finding it difficult to find a simple suitable way to mock this.
Any help with this matter will be greatly appreciated.
Mocking the linq-to-sql context is indeed a huge task. I usually work around it by letting my unit tests run against a separate database copy, with data specially crafted to fit the unit tests. (I know it can be argued that it's no longer unit tests, but rather integration tests, but I don't care as long as I get the code tested).
To keep the database in a known state I wrap each test in a TransactionScope which is rolled back at the end of the test. That way the state of the database is never changed.
A sample test method looks like this:
[TestMethod]
public void TestRetire()
{
using (TransactionScope transaction = new TransactionScope())
{
Assert.IsTrue(Car.Retire("VLV100"));
Assert.IsFalse(Car.Retire("VLV100"));
// Deliberately not commiting transaction.
}
}
The code is from a blog post about the method I wrote some time ago: http://coding.abel.nu/2011/12/using-transactions-for-unit-tests/
Since you request a way to mock a DataContext I assume that you really want to do some unit tests and not integration tests.
Well, I will tell you how to accomplish this, but first I would like to encourage you to read the following links, they are all about writing clean testable code.
http://misko.hevery.com/code-reviewers-guide/
http://misko.hevery.com/attachments/Guide-Writing%20Testable%20Code.pdf
And check the links from this response:
https://stackoverflow.com/a/10359288/1268570
Watch the clean code talks from Misko Hevery (given to the Google people)
http://www.youtube.com/watch?v=wEhu57pih5w&feature=player_embedded
http://www.youtube.com/watch?v=RlfLCWKxHJ0&feature=player_embedded
http://www.youtube.com/watch?v=-FRm3VPhseI&feature=player_embedded
http://www.youtube.com/watch?v=4F72VULWFvc&feature=player_embedded
One thing that I used to repeat to myself and to my fellows at work, is that anyone can write a unit test, because they are silly easy to write. So a simple test is essentially all about making some comparisons and throw exceptions if the results fails, anyone can do that. Of course, there are hundreds of frameworks to help us write those tests in an elegant way. But the real deal, and the real effort shroud be put on learn how to write clean testable code
Even if you hire Misko Hevery to help you write tests, he will have a real hard time writing them if your code is not test-friendly.
Now the way to mock a DataContext objects is: do not do it
Instead wrap the calls using a custom interface instead:
public interface IMyDataContextCalls
{
void Save();
IEnumerable<Product> GetOrders();
}
// this will be your DataContext wrapper
// this wll act as your domain repository
public class MyDataContextCalls : IMyDataContextCalls
{
public MyDataContextCalls(DataClasses1DataContext context)
{
this.Context = context;
}
public void Save()
{
this.Context.SubmitChanges();
}
public IEnumerable<Product> GetOrders()
{
// place here your query logic
return this.Context.Products.AsEnumerable();
}
private DataClasses1DataContext Context { get; set; }
}
// this will be your domain object
// this object will call your repository wrapping the DataContext
public class MyCommand
{
private IMyDataContextCalls myDataContext;
public MyCommand(IMyDataContextCalls myDataContext)
{
this.myDataContext = myDataContext;
}
public bool myDomainRule = true;
// assume this will be the SUT (Subject Under Test)
public void Save()
{
// some business logic
// this logic will be tested
if (this.myDomainRule == true)
{
this.myDataContext.Save();
}
else
{
// handle your domain validation errors
throw new InvalidOperationException();
}
}
}
[TestClass]
public class MyTestClass
{
[TestMethod]
public void MyTestMethod()
{
// in this test your mission is to test the logic inside the
// MyCommand.Save method
// create the mock, you could use a framework to auto mock it
// or create one manually
// manual example:
var m = new MyCommand(new MyFakeDataContextFake());
m.Invoking(x => x.Save())
//add here more asserts, maybe asserting that the internal
// state of your domain object was changed
// your focus is to test the logic of the domain object
.ShouldNotThrow();
//auto mock example:
var fix = new Fixture().Customize(new AutoMoqCustomization());
var sut = fix.CreateAnonymous<MyCommand>();
sut.myDomainRule = false;
sut.Invoking(x => x.Save())
.ShouldThrow<InvalidOperationException>();
}
public class MyFakeDataContextFake : IMyDataContextCalls
{
public void Save()
{
// do nothing, since you do not care in the logic of this method,
// remember your goal is to test the domain object logic
}
public IEnumerable<Product> GetOrders()
{
// we do not care on this right now because we are testing only the save method
throw new NotImplementedException();
}
}
}
Notes:
When you declare your IMyDataContextCalls interface you are actually abstracting the use of a DataContext, therefore this interface should contain only POCO objects (most of the time), if you follow this approach your interfaces will be decoupled from any undesired dependency.
In the specific MyDataContextCalls implementation, you are explicitly using a DataClasses1DataContext context, but you are free to change the implementation at any time and that won't affect your external code, and that's because you are always working with the IMyDataContextCalls interface instead. So at any time you could change for example this implementation for another one using the wonderful NHibernate =) or the poor ef or a mock one
At last, but not least. please double check my code, and you will notice that there are no new operators in the domain objects. This is a rule of dumb when writing test friendly code: decouple the responsibility of creating objects outside of your domain objects
I personally use three frameworks on every project and on every test I write, I really recommend them:
AutoFixture
Moq
FluentAssertions
For example, in the code above, I showed you how to write a manual fake for your repository, but that clearly is something we do not want to do in a real project, imagine the number of objects you would have to code in order to write your tests.
Instead use the power of AutoFixture combined with Moq:
This line: var m = new MyCommand(new MyFakeDataContextFake());
Will become:
var fixture = new Fixture().Customize(new AutoMoqCustomization());
var sut = fixture.CreateAnonymous<MyCommand>();
And that's it, this code will automatically create mocks for all the objects needed in the constructor of MyCommand.
In short, you don't mock DataContext. You extract interface from it and mock that interface using some collections for entity sets, and then verify contents of those collections.
Here is my problem:
I have an n-tiers application for which I have to write unit tests. Unit tests are for the business layer.
I have a method to test called Insert() and this one use two protected methods from inheritance and call directly a method from Data access layer.
So I have made a mock object for the DAL. But here is the point, in a (edit :) protected method from inheritance, It will use another object from DAL! It seems it is not possible to mock this one!
Here is the method for test code:
public int Insert(MYOBJECT aMyObject)
{
//first inherited method use the FIRSTDALOBJECT so the mock object --> No problem
aMyObject.SomeField= FirstInherited();
//Second inherited method (see after) --> my problem
aMyObject.SomeOtherField = SecondInherited();
// Direct access to DALMethod, use FIRSTDALOBJECT so the mock -->No Problem
return this.FIRSTDALOBJECT.Insert(aMyObject);
}
Here is the SecondInherited method:
protected string SecondInherited ()
{
// Here is my problem, the mock here seems not be possible for seconddalobject
return ( new SECONDDALOBJECT Sdo().Stuff());
}
And here is the unit test method code :
[TestMethod()]
public void InsertTest()
{
BLLCLASS_Accessor target = new BLLCLASS_Accessor();
MYOBJECT aMyObject = new MYOBJECT { SomeField = null, SomeOtherField = 1 };
int expected = 1;
int actual;
//mock
var Mock = new Mock<DAL.INTERFACES.IFIRSTDALOBJECT>();
//Rec for calls
List<SOMECLASS> retour = new List<SOMECLASS>();
retour.Add(new SOMECLASS());
//Here is the second call (last from method to test)
Mock
.Setup(p => p.Insert(aMyObject))
.Returns(1);
// Here is the first call (from the FirstInherited())
Mock
.Setup(p => p.GetLast())
.Returns(50);
// Replace the real by the mock
target.demande_provider = Mock.Object;
actual = target.Insert(aMyObject);
Assert.AreEqual(/*Some assertion stuff*/);
}
Thank you for reading all the question :-) Hope it is clear enough.
Your text seems to say that SecondInherited is private, while in the code example it is protected. Anyway, if it is not protected, I would suggest changing its access qualifier as the first step.
You can create a subclass solely for testing purposes, and override SecondInherited there to avoid creating SECONDDALOBJECT and just return some value suitable for your tests.
This way you can write your first unit test(s) with minimal changes to the class being tested, thus minimizing the chances of breaking something. Once you have the unit tests in place, these allow you to do more refactoring safely, eventually achieving a better (more testable / mockable) design, such as using Dependency Injection, or a Factory. (I would probably prefer an Abstract Factory over Factory Method here, as the latter would practically force you to keep subclassing the tested class).
The fundamental, highly recommended book for learning this technique (and many more) is Working Effectively With Legacy Code.
No chance to mock this with MOQ.
You have two options:
Use TypeMock or Moles to mock the SECONDDALOBJECT class
Refactor the code, so the instance of SECONDDALOBJECT isn't created in the way it is, but in a way that can be mocked (Factory method, DI, ...) (prefered!)
I have a method that takes 5 parameters. This method is used to take a bunch of gathered information and send it to my server.
I am writing a unit test for this method, but I am hitting a bit of a snag. Several of the parameters are Lists<> of classes that take some doing to setup correctly. I have methods that set them up correctly in other units (production code units). But if I call those then I am kind of breaking the whole idea of a unit test (to only hit one "unit").
So.... what do I do? Do I duplicate the code that sets up these objects in my Test Project (in a helper method) or do I start calling production code to setup these objects?
Here is hypothetical example to try and make this clearer:
File: UserDemographics.cs
class UserDemographics
{
// A bunch of user demographic here
// and values that get set as a user gets added to a group.
}
File: UserGroups.cs
class UserGroups
{
// A bunch of variables that change based on
// the demographics of the users put into them.
public AddUserDemographicsToGroup(UserDemographcis userDemographics)
{}
}
File: UserSetupEvent.cs
class UserSetupEvent
{
// An event to record the registering of a user
// Is highly dependant on UserDemographics and semi dependant on UserGroups
public SetupUserEvent(List<UserDemographics> userDemographics,
List<UserGroup> userGroups)
{}
}
file: Communications.cs
class Communications
{
public SendUserInfoToServer(SendingEvent sendingEvent,
List<UserDemographics> userDemographics,
List<UserGroup> userGroups,
List<UserSetupEvent> userSetupEvents)
{}
}
So the question is: To unit test SendUserInfoToServer should I duplicate SetupUserEvent and AddUserDemographicsToGroup in my test project, or should I just call them to help me setup some "real" parameters?
You need test duplicates.
You're correct that unit tests should not call out to other methods, so you need to "fake" the dependencies. This can be done one of two ways:
Manually written test duplicates
Mocking
Test duplicates allow you to isolate your method under test from its dependencies.
I use Moq for mocking. Your unit test should send in "dummy" parameter values, or statically defined values you can use to test control flow:
public class MyTestObject
{
public List<Thingie> GetTestThingies()
{
yield return new Thingie() {id = 1};
yield return new Thingie() {id = 2};
yield return new Thingie() {id = 3};
}
}
If the method calls out to any other classes/methods, use mocks (aka "fakes"). Mocks are dynamically-generated objects based on virtual methods or interfaces:
Mock<IRepository> repMock = new Mock<IRepository>();
MyPage obj = new MyPage() //let's pretend this is ASP.NET
obj.IRepository = repMock.Object;
repMock.Setup(r => r.FindById(1)).Returns(MyTestObject.GetThingies().First());
var thingie = MyPage.GetThingie(1);
The Mock object above uses the Setup method to return the same result for the call defined in the r => r.FindById(1) lambda. This is called an expecation. This allows you to test only the code in your method, without actually calling out to any dependent classes.
Once you've set up your test this way, you can use Moq's features to confirm that everything happened the way it was supposed to:
//did we get the instance we expected?
Assert.AreEqual(thingie.Id, MyTestObject.GetThingies().First().Id);
//was a method called?
repMock.Verify(r => r.FindById(1));
The Verify method allows you to test whether a method was called. Together, these facilities allow you focus your unit tests on a single method at a time.
Sounds like your units are too tightly coupled (at least from a quick view at your problem). What makes me curious is for instance the fact that your UserGroups takes a UserDemographics and your UserSetupEvent takes a list of UserGroup including a list of UserDemographics (again). Shouldn't the List<UserGroup> already include the ÙserDemographics passed in it's constructor or am I misunderstanding it?
Somehow it seems like a design problem of your class model which in turn makes it difficult to unit test. Difficult setup procedures are a code smell indicating high coupling :)
Bringing in interfaces is what I would prefer. Then you can mock the used classes and you don't have to duplicate code (which violates the Don't Repeat Yourself principle) and you don't have to use the original implementations in the unit tests for the Communications class.
You should use mock objects, basically your unit test should probably just generate some fake data that looks like real data instead of calling into the real code, this way you can isolate the test and have predictable test results.
You can make use of a tool called NBuilder to generate test data. It has a very good fluent interface and is very easy to use. If your tests need to build lists this works even better. You can read more about it here.
This is a sample function that works with an entity, saves it to a db and then causes problems because we can't write a Unit Test for it. Check it out:
// this class exists in a Silverlight Class Library
public class EmployeeSaver
{
....
public void Go()
{
Employee e = new Employee();
e.Name="Jeremiah";
... // Other stuff that really needs to be tested
_DataContext.Employees.Add(e);
_DataContext.SubmitChanges();
}
}
Because the nature of RIA Services, a DomainService doesn't run inside of the Silverlight Unit Testing framework. This means I don't have access to RIA when I do my unit tests.
We've thought about mock databases, but this class actually creates an Entity (Employee) to be added to the DB. This is problematic because Mock Databases don't use this entity but a MockEntity class that looks similar to the original entity.
We're not trying to test RIA itself, but how we use the entities generated by RIA.
My end goal would be to write a function similar to this:
[TestMethod]
public void Test()
{
EmployeeSaver s = new EmployeeSaver();
s.Go();
Assert.IsEqual( DataContext.Employees.Last().Name, "Jeremiah" );
}
How can I test this function? What testing framework should I use? Am I way off for using the Silverlight Testing Framework?
In your unit test, instance s needs to have a stubbed out implementation of _DataContext. When the Go method is called, and it calls:
_DataContext.Employees.Add(e);
_DataContext.SubmitChanges();
it will call into your stub. The stub should then record the fact that an employee got added and changes were submitted.
After the call to Go, you should query the stub to ensure that the new employee got added, and call to SubmitChanges occurred.
As a secondary note:
I don't really agree with the last part of the other answer in that you should not care whether Go calls various methods of _DataContext. It is true that you're not concerned about testing _DataContext methods here, but the unit test for Go needs to ensure that the Go method is calling the _DataContext methods properly. The rationale is that every line of the Go method should be testable. If you didn't do this verification, then you could remove the calls to _DataContext method, breaking the code, but the unit test wouldn't catch it. This would break Bob Martin's the "three rules of TDD" principle.
A hand rolled mock database could store your object as is. We use such a system where the repositories are stored in dictionaries of .
You don't even need to go that far though. You could just use a mock interface for the _DataContext with something like RhinoMocks to make sure that the methods you expect to be called were (its not your concern for this test that _DataContext.SubmitChanges() works (that would be up it it's unit test) you only care that Go set the object and called save.