I am trying to setup unit tests for my Linq To SQL code. My code uses the System.Data.Linq.Table class (generated by the designer).
Because this class is sealed and the constructor is internal it is completely impervious to unit testing frameworks like Rhino Mocks. (Unless you want to alter you code to use the repository pattern, which I would rather not.)
Typemock can (some how) mock this class. (See here for an example.)
However, Typemock is also $800 a license. I don't see my employer springing for that anytime soon.
So here is the question. Are there any other mocking frameworks out there that don't rely on Interfaces to create the mocks?
Edit: Example of code that I need to test:
public class UserDAL : IUserDAL
{
private IDataClassesDataContext _ctx;
public UserDAL()
{
string env = ConfigurationManager.AppSettings["Environment"];
string connectionString = ConfigurationManager
.ConnectionStrings[env].ConnectionString;
_ctx = new DataClassesDataContext(connectionString);
}
public UserDAL(IDataClassesDataContext context)
{
_ctx = context;
}
public List<User> GetUsersByOrganization(int organizationId)
{
IOrderedQueryable<User> vUsers =
(from myUsers in _ctx.Users
where myUsers.Organization == organizationId
orderby myUsers.LastName
select myUsers);
return vUsers.ToList();
}
public bool IsUserInOrganization(User user, int orga开发者_如何转开发inzationID)
{
// Do some Dal Related logic here.
return GetUsersByOrganization(orgainzationID).Contains(user);
}
}
I have shorted this up to make it easier to read. The idea is that I have some code (like IsUserInOrganization
that calls another method (like GetUsersByOrganization
) that does a Linq query.
I would like to unit test the IsUserInOrganization
method. Do do that I would need to mock _ctx.Users which is a Table class (that is sealed and has an internal constructor).
Check out Microsoft Stubs that has the simple premise of:
Replace any .NET method with your own delegate!
And a more detailed description of it's capabilities (emphasis is mine).
Stubs is a lightweight framework for test stubs and detours in .NET that is entirely based on delegates, type safe, refactorable and source code generated. Stubs was designed provide a minimal overhead to the Pex white box analysis, support the Code Contracts runtime writer and encourage the programmatic models rather than record/replay tests. Stubs may be used on any .NET method, including non-virtual/static methods in sealed types.
There are two standard unit testing approaches in this case:
1) Don't test the platform - if the dependency is on a framework class, you don't write tests where that interaction is verified. This typically means you substitute a dependency at test time, but in your case it likely means you inject the table itself.
2) Wrap the platform - if you need to test something that interacts with the platform, then write a wrapper layer for the relevant components
There's also integration and acceptance testing to consider. For both of these cases you would usually simply accept the dependency as it exists in your application.
What precisely are you concerned about testing that you need to directly mock/substitute this class?
Edit:
It seems as if you're looking to avoid rewriting code to be more testable. This is where TypeMock excels, and is the reason why some test advocates think TypeMock can lead to problems. It is, however, the right tool for the job if you absolutely refuse to restructure your code for testability.
Edit #2:
Perhaps I'm being overly obsessive about this, but let's consider a more testable pattern:
Organization()
{
HasUser(name)
}
OrganizationDAL
{
Organization LoadOrganization(id)
}
OrganizationServiceFacade
{
IsUserInOrganization(name, orgid)
{
return OrgDAL.LoadOrganization(id).HasUser(name)
}
}
Organization's natural contains test for a user no longer needs to be platform-dependent, you should be able to inject the datasource. OrganizationDAL is only responsible for loading organizations rather than returning information about organizations (although there are ways to put queries into this layer if necessary). OrganizationServiceFacade is only responsible for providing composed services, which should both satisfy mockability and avoid the need for extra unit tests (it's an Integration or possibly even an Acceptance target) since it's a wrapper class. Depending on how you construct Organizations, you can inject data without relying on a particular notion of how that data works.
You may want to consider using the Repository pattern, basically it's the "wrap the platform" suggestion from Mike. With it you'll be mocking IRepository rather then the DataContext.
http://blogs.microsoft.co.il/blogs/kim/archive/2008/11/14/testable-data-access-with-the-repository-pattern.aspx
精彩评论