I have a class for products (MyProduct) and then another class (ProductAnalyzer) for performing various options on a collection of products.
I want to do unit testing on these classes. Specifically, testing if product is X days old or older.
There is already a function called ProductAnalyzer.tenDaysOld() that will do this. As long as instances of MyProduct are in the ProductAnalyzer collection, it will do the calculation.
In order to run tests, I need a way to somehow modify timestamps on MyProduct instances so they are older than 10 days. Or perhaps modify tenDaysOld(). Either way, I'm guessing they'll need to be mocked.
In MyProduct, productCreated is timestamped and private. I'd like to keep it that way but that means it can't be tested. If I modify it to public, I can test it but then I'm changing the code base just for testing purposes, which has nothing to do with actual functionality in production (isn't that bad practice?).
Any suggestions how I can approach this?
Below are simplified versions of the classes with relevant code shown.
class MyProduct: NSObject {
private var productCreated:Date
init(){
productCreated = Date()
}
}
class ProductAnalyzer {
static var products:[InventoryItem] = []
static func tenDaysOld() {
let tenDays = NSCalendar.current.date(byAdding: Calendar.Component.day, value: 10, to: Date())
let oldProducts = ProductAnalyzer.products.filter({ $0.dateAdded.compare(tenDays!) == .orderedDescending })
}
}
Related
I am trying to pass data from Activity A to Activity B but without using Intent putExtra nor using SharePreferences, I'm using a MVVM pattern in kotlin, so right now I'm using an object declaration like this
object SharedData{ var myMovies: ArrayList<Movie>? = null }
So later on in Activity A i'm assigning a value like this
val movieList = ArrayList<Movie>()
movieList.add(Movie("The Purge"))
SharedData.myMovies = movieList
And then in Activity B i retrieve this value by:
val movieList = ArrayList<Movie>()
SharedData.myMovies.let {
movieList = it
}
But I'm new in kotlin and now I know this is not the correct approach. because the singleton object allocates memory and it never gets collected by the GC. So now I'm stucked here.
Any guidance or help would be appreciated
So, if you're using MVVM pattern it's very straight forward. Use the basic ViewModel implementation with Android Architecture Components. See more of this in https://developer.android.com/topic/libraries/architecture/
class MyActivity : AppCompatActivity() {
private lateinit var myViewModel: MyViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.my_layout)
myViewModel = ViewModelProviders.of(this).get(MyViewModel::class.java)
myViewModel.myObject.observe(this, Observer { mySharedObject ->
//TODO whatever you want to do with your data goes here
Log.i("SomeTag", mySharedObject.anyData)
})
}
}
class MyCoachFragment : Fragment() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
activity?.let {
myViewModel = ViewModelProviders.of(it).get(MyViewModel::class.java)
}
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val myObject = MyObject() // what ever object you need to share between Activities and Fragments, it could be a data class or any object
myViewModel.myObject.postValue(myObject)
}
}
class MyViewModel : ViewModel() {
var myObject = MutableLiveData<MyObject>()
}
My suggestion would be - If you want to share the data just between two activities, you should use intent and send the content as parcelable Object( parcelableArray for your Movielist scenario ) to the next activity. This would be clean implementation.
But I'm new in kotlin and now I know this is not the correct approach.
It is not wrong approach either, can be used depends on your use case. If it meets all the below scenarios, you can go for static variable approach. But Static object will be cleared when the app is killed (either by user or by system)
1.If the stored data size is less.
2.Data does not need to be persisted on App kill and relaunch.
3.Data is shared across many activities.
the singleton object allocates memory and it never gets collected by
the GC
Yes. It's true. Static variables are not eligible for garbage collection. But as long as the memory print is very less, it's okay to use static variable provided it meets above mentioned scenarios.
This was asked during an interview.
There are different manufacturers of buses. Each bus has got different models and each model has only 2 variants. So different manufacturers have different models with only 2 variants. The interviewer asked me to design a standalone program with just classes. She mentioned that I should not think about databases and I didn't have to code them. For example, it could be a console based program with inputs and outputs.
The manufacturers, models and variants information should be held in memory (hard-coded values were fine for this standalone program). She wanted to observe the classes and my problem solving approach.
She told me to focus on implementing three APIs or methods for this system.
The first one was to get information about a particular bus. Input would be manufacturer name, model name and variant name. Given these three values, the information about a particular bus such as its price, model, year, etc should be shown to the client.
The second API would be to compare two buses and the output would be to list the features side by side, probably in a tabular format. Input would be the same as the one for the first API i.e. manufacturer name, model name and variant name for both the buses.
The third one would be to search the buses by price (>= price) and get the list of buses which satisfy the condition.
She also added that the APIs should be scalable and I should design the solution with this condition on my mind.
This is how I designed the classes:
class Manufacturer {
private String name;
private Set<Model> models;
// some more properties related to manufacturer
}
class Model {
private String name;
private Integer year;
private Set<Variant> variants;
// some more properties related to model
}
class Variant {
private String name;
private BigDecimal price;
// some more properties related to variant
}
class Bus {
private String manufacturerName;
private String modelName;
private String variantName;
private Integer year;
private BigDecimal price;
// some more additional properties as required by client
}
class BusService {
// The first method
public Bus getBusInformation(String manufacturerName, String modelName, String variantName) throws Exception {
Manufacturer manufacturer = findManufacturer(manufacturerName);
//if(manufacturer == null) throw a valid exception
Model model = findModel(manufacturer);
// if(model == null) throw a valid exception
Variant variant = findVariant(model);
// if(variant == null) throw a valid exception
return createBusInformation(manufacturer, model, variant);
}
}
She stressed that there were only 2 variants and there wouldn't be any more variants and it should be scalable. After going through the classes, she said she understood my approach and I didn't have to implement the other APIs/methods. I realized that she wasn't impressed with the way I designed them.
It would be helpful to understand the mistake I made so that I could learn from it.
I interpreted your 3 requirements a bit differently (and I may be wrong). But it sounds like the overall desire is to be able to perform different searches against all Models, correct?
Also, sounds to me that as all Variants are Models. I suspect different variants would have different options, but nothing to confirm that. If so, a variant is just a subclass of a particular model. However, if variants end up having the same set of properties, then variant isn't anything more than an additional descriptor to the model.
Anyway, going on my suspicions, I'd have made Model the center focus, and gone with:
(base class)
abstract class Model {
private Manufacturer manufacturer;
private String name;
private String variant;
private Integer year;
private BigDecimal price;
// some more properties related to model
}
(manufacturer variants)
abstract class AlphaModel {
AlphaModel() {
this.manufacturer = new Manufacturer() { name = "Alpha" }
}
// some more properties related to this manufacturer
}
abstract class BetaModel {
BetaModel() {
this.manufacturer = new Manufacturer() { name = "Beta" }
}
// some more properties related to this manufacturer
}
(model variants)
abstract class AlphaBus : AlphaModel {
AlphaBus() {
this.name = "Super Bus";
}
// some more properties related to this model
}
abstract class BetaTruck : BetaModel {
BetaTruck() {
this.name = "Big Truck";
}
// some more properties related to this model
}
(actual instances)
class AlphaBusX : AlphaBus {
AlphaBusX() {
this.variant = "X Edition";
}
// some more properties exclusive to this variant
}
class AlphaBusY : AlphaBus {
AlphaBusY() {
this.variant = "Y Edition";
}
// some more properties exclusive to this variant
}
class BetaTruckF1 : BetaTruck {
BetaTruckF1() {
this.variant = "Model F1";
}
// some more properties exclusive to this variant
}
class BetaTruckF2 : BetaTruck {
BetaTruckF2() {
this.variant = "Model F2";
}
// some more properties exclusive to this variant
}
Then finally:
var data = new Set<Model> {
new AlphaBusX(),
new AlphaBusY(),
new BetaTruckF1(),
new BetaTruckF2()
}
API #1:
var result = data.First(x => x.manufacturer.name = <manufactuer>
&& x.name = <model>
&& x.variant = <variant>);
API #2:
var result1 = API#1(<manufacturer1>, <model1>, <variant1>);
var result2 = API#1(<manufacturer2>, <model2>, <variant2>);
API #3:
var result = data.Where(x => x.price >= <price>);
I would say your representation of the Bus class is severely limited, Variant, Model, Manufacturer should be hard links to the classes and not strings. Then a get for the name of each.
E.G from the perspective of Bus bus1 this.variant.GetName() or from the outside world. bus1.GetVariant().name
By limiting your bus to strings of it's held pieces, you're forced to do a lookup even when inside the bus class, which performs much slower at scale than a simple memory reference.
In terms of your API (while I don't have an example), your one way to get bus info is limited. If the makeup of the bus changes (variant changes, new component classes are introduced), it requires a decent rewrite of that function, and if other functions are written similarly then all of those two.
It would require some thought but a generic approach to this that can dynamically grab the info based on the input makes it easier to add/remove component pieces later on. This will be the are your interviewer was focusing on most in terms of advanced technical&language skills. Implementing generics, delegates, etc. here in the right way can make future upkeep of your API a lot easier. (Sorry I don't have an example)
I wouldn't say your approach here is necessarily bad though, the string member variables are probably the only major issue.
I have a class that I want to test using XCTest, and this class looks something like this:
public class MyClass: NSObject {
func method() {
// Do something...
// ...
SingletonClass.sharedInstance.callMethod()
}
}
The class uses a singleton that is implemented as this:
public class SingletonClass: NSObject {
// Only accessible using singleton
static let sharedInstance = SingletonClass()
private override init() {
super.init()
}
func callMethod() {
// Do something crazy that shouldn't run under tests
}
}
Now for the test. I want to test that method() actually does what it is supposed to do, but I don't want to invoke the code in callMethod() (because it does some horrible async/network/thread stuff that shouldn't run under tests of MyClass, and will make the tests crash).
So what I basically would like to do is this:
SingletonClass = MockSingletonClass: SingletonClass {
override func callMethod() {
// Do nothing
}
let myObject = MyClass()
myObject.method()
// Check if tests passed
This obviously isn't valid Swift, but you get the idea. How can I override callMethod() just for this particular test, to make it harmless?
EDIT: I tried solving this using a form of dependency injection, but ran into big problems. I created a custom init-method just to be used for tests such that I could create my objects like this:
let myObject = MyClass(singleton: MockSingletonClass)
and let MyClass look like this
public class MyClass: NSObject {
let singleton: SingletonClass
init(mockSingleton: SingletonClass){
self.singleton = mockSingleton
}
init() {
singleton = SingletonClass.sharedInstance
}
func method() {
// Do something...
// ...
singleton.callMethod()
}
}
Mixing in test code with the rest of the code is something I find a bit unpleasing, but okay. The BIG problem was that I had two singletons constructed like this in my project, both referencing each other:
public class FirstSingletonClass: NSObject {
// Only accessible using singleton
static let sharedInstance = FirstSingletonClass()
let secondSingleton: SecondSingletonClass
init(mockSingleton: SecondSingletonClass){
self.secondSingleton = mockSingleton
}
private override init() {
secondSingleton = SecondSingletonClass.sharedInstance
super.init()
}
func someMethod(){
// Use secondSingleton
}
}
public class SecondSingletonClass: NSObject {
// Only accessible using singleton
static let sharedInstance = SecondSingletonClass()
let firstSingleton: FirstSingletonClass
init(mockSingleton: FirstSingletonClass){
self.firstSingleton = mockSingleton
}
private override init() {
firstSingleton = FirstSingletonClass.sharedInstance
super.init()
}
func someOtherMethod(){
// Use firstSingleton
}
}
This created a deadlock when one of the singletons where first used, as the init method would wait for the init method of the other, and so on...
Your singletons are following a very common pattern in Swift/Objective-C code bases. It is also, as you have seen, very difficult to test and an easy way to write untestable code. There are times when a singleton is a useful pattern but my experience has been that most uses of the pattern are actually a poor fit for the needs of the app.
The +shared_ style singleton from Objective-C and Swift class constant singletons usually provide two behaviors:
It might enforce that only a single instance of a class can be instantiated. (In practice this is often not enforced and you can continue to alloc/init additional instances and the app instead depends on developers following a convention of exclusively accessing a shared instance via the class method.)
It acts as a global, allowing access to a shared instance of a class.
Behavior #1 is occasionally useful while behavior #2 is just a global with a design pattern diploma.
I would resolve your conflict by removing the globals entirely. Inject your dependencies all of the time instead of just for testing and consider what responsibility that exposes in your app when you need something to coordinate whatever set of shared resources you're injecting.
A first pass at injecting dependencies throughout an app is often painful; "but I need this instance everywhere!". Use it as a prompt to reconsider the design, why are so many components accessing the same global state and how might it be modeled instead to provide better isolation?
There are cases where you want a single copy of some mutable shared state and a singleton instance is perhaps the best implementation. However I find that in most examples that still doesn't hold true. Developers are usually looking for shared state but with some conditions: there's only one screen until an external display is connected, there's only one user until they sign out and into a second account, there's only one network request queue until you find a need for authenticated vs anonymous requests. Similarly you often want a shared instance until the execution of the next test case.
Given how few "singleton"s seem to use failable initializers (or obj-c init methods which return an existing shared instance) it seems that developers are happy to share this state by convention so I see no reason not to inject the shared object and write readily testable classes instead of using globals.
I eventually solved this using the code
class SingletonClass: NSObject {
#if TEST
// Only used for tests
static var sharedInstance: SingletonClass!
// Public init
override init() {
super.init()
}
#else
// Only accessible using singleton
static let sharedInstance = SingletonClass()
private override init() {
super.init()
}
#endif
func callMethod() {
// Do something crazy that shouldn't run under tests
}
}
This way I can easily mock my class during tests:
private class MockSingleton : SingletonClass {
override callMethod() {}
}
In tests:
SingletonClass.sharedInstance = MockSingleton()
The test-only code is activated by adding -D TEST to "Other Swift Flags" in Build Settings for the app test target.
I had a similar issue in my app, and in my case it made sense to use Singletons for these particular services as they were proxies for external services that were also singletons.
I ended up implementing a Dependency Injection model using https://github.com/Swinject/Swinject. It took about a day to implement for about 6 classes which seems like a lot of time to enable this level of unit testability. It did make me think hard about the dependencies between my service classes, and it made me more explicitly indicate these in the class definitions. I used the ObjectScope in Swinject to indicate to the DI framework that they're singletons: https://github.com/Swinject/Swinject/blob/master/Documentation/ObjectScopes.md
I was able to have my singletons, and pass in mock versions of them to my unit tests.
Thoughts on this approach: it seems more error prone as I could forget to initialize my dependencies correctly (and would never receive a runtime error). Finally, it doesn't prevent someone from just instantiating a instance of my Service class directly (which was sort of the whole point of the singleton), since my init methods had to be made public for the DI Framework to instantiate the objects into the registry.
I would suggest to make init not private (quite not convenient), but don't see better solution for now that object can be tested, if you need to simulate multi calls of initializing of the data type.
Does anyone know the best way to refactor a God-object?
Its not as simple as breaking it into a number of smaller classes, because there is a high method coupling. If I pull out one method, i usually end up pulling every other method out.
It's like Jenga. You will need patience and a steady hand, otherwise you have to recreate everything from scratch. Which is not bad, per se - sometimes one needs to throw away code.
Other advice:
Think before pulling out methods: on what data does this method operate? What responsibility does it have?
Try to maintain the interface of the god class at first and delegate calls to the new extracted classes. In the end the god class should be a pure facade without own logic. Then you can keep it for convenience or throw it away and start to use the new classes only
Unit Tests help: write tests for each method before extracting it to assure you don't break functionality
I assume "God Object" means a huge class (measured in lines of code).
The basic idea is to extract parts of its functions into other classes.
In order to find those you can look for
fields/parameters that often get used together. They might move together into a new class
methods (or parts of methods) that use only a small subset of the fields in the class, the might move into a class containing just those field.
primitive types (int, String, boolean). They often are really value objects before their coming out. Once they are value object, they often attract methods.
look at the usage of the god object. Are there different methods used by different clients? Those might go in separate interfaces. Those intefaces might in turn have separate implementations.
For actually doing these changes you should have some infrastructure and tools at your command:
Tests: Have a (possibly generated) exhaustive set of tests ready that you can run often. Be extremely careful with changes you do without tests. I do those, but limit them to things like extract method, which I can do completely with a single IDE action.
Version Control: You want to have a version control that allows you to commit every 2 minutes, without really slowing you down. SVN doesn't really work. Git does.
Mikado Method: The idea of the Mikado Method is to try a change. If it works great. If not take note what is breaking, add them as dependency to the change you started with. Rollback you changes. In the resulting graph, repeat the process with a node that has no dependencies yet. http://mikadomethod.wordpress.com/book/
According to the book "Object Oriented Metrics in Practice" by Lanza and Marinescu, The God Class design flaw refers to classes that tend to centralize the intelligence of the system. A God Class performs too much work on its own, delegating only minor details to a set of trivial classes and using the data from other classes.
The detection of a God Class is based on three main characteristics:
They heavily access data of other simpler classes, either directly or using accessor methods.
They are large and complex
They have a lot of non-communicative behavior i.e., there is a low
cohesion between the methods belonging to that class.
Refactoring a God Class is a complex task, as this disharmony is often a cumulative effect of other disharmonies that occur at the method level. Therefore, performing such a refactoring requires additional and more fine-grained information about the methods of the class, and sometimes even about its inheritance context. A first approach is to identify clusters of methods and attributes that are tied together and to extract these islands into separate classes.
Split Up God Class method from the book "Object-Oriented Reengineering Patterns" proposes to incrementally redistribute the responsibilities of the God Class either to its collaborating classes or to new classes that are pulled out of the God Class.
The book "Working Effectively with Legacy Code" presents some techniques such as Sprout Method, Sprout Class, Wrap Method to be able to test the legacy systems that can be used to support the refactoring of God Classes.
What I would do, is to sub-group methods in the God Class which utilize the same class properties as inputs or outputs. After that, I would split the class into sub-classes, where each sub-class will hold the methods in a sub-group, and the properties which these methods utilize.
That way, each new class will be smaller and more coherent (meaning that all their methods will work on similar class properties). Moreover, there will be less dependency for each new class we generated. After that, we can further reduce those dependencies since we can now understand the code better.
In general, I would say that there are a couple of different methods according to the situation at hand. As an example, let's say that you have a god class named "LoginManager" that validates user information, updates "OnlineUserService" so the user is added to the online user list, and returns login-specific data (such as Welcome screen and one time offers)to the client.
So your class will look something like this:
import java.util.ArrayList;
import java.util.List;
public class LoginManager {
public void handleLogin(String hashedUserId, String hashedUserPassword){
String userId = decryptHashedString(hashedUserId);
String userPassword = decryptHashedString(hashedUserPassword);
if(!validateUser(userId, userPassword)){ return; }
updateOnlineUserService(userId);
sendCustomizedLoginMessage(userId);
sendOneTimeOffer(userId);
}
public String decryptHashedString(String hashedString){
String userId = "";
//TODO Decrypt hashed string for 150 lines of code...
return userId;
}
public boolean validateUser(String userId, String userPassword){
//validate for 100 lines of code...
List<String> userIdList = getUserIdList();
if(!isUserIdValid(userId,userIdList)){return false;}
if(!isPasswordCorrect(userId,userPassword)){return false;}
return true;
}
private List<String> getUserIdList() {
List<String> userIdList = new ArrayList<>();
//TODO: Add implementation details
return userIdList;
}
private boolean isPasswordCorrect(String userId, String userPassword) {
boolean isValidated = false;
//TODO: Add implementation details
return isValidated;
}
private boolean isUserIdValid(String userId, List<String> userIdList) {
boolean isValidated = false;
//TODO: Add implementation details
return isValidated;
}
public void updateOnlineUserService(String userId){
//TODO updateOnlineUserService for 100 lines of code...
}
public void sendCustomizedLoginMessage(String userId){
//TODO sendCustomizedLoginMessage for 50 lines of code...
}
public void sendOneTimeOffer(String userId){
//TODO sendOneTimeOffer for 100 lines of code...
}}
Now we can see that this class will be huge and complex. It is not a God class by book definition yet, since class fields are commonly used among methods now. But for the sake of argument, we can treat it as a God class and start refactoring.
One of the solutions is to create separate small classes which are used as members in the main class. Another thing you could add, could be separating different behaviors in different interfaces and their respective classes. Hide implementation details in classes by making those methods "private". And use those interfaces in the main class to do its bidding.
So at the end, RefactoredLoginManager will look like this:
public class RefactoredLoginManager {
IDecryptHandler decryptHandler;
IValidateHandler validateHandler;
IOnlineUserServiceNotifier onlineUserServiceNotifier;
IClientDataSender clientDataSender;
public void handleLogin(String hashedUserId, String hashedUserPassword){
String userId = decryptHandler.decryptHashedString(hashedUserId);
String userPassword = decryptHandler.decryptHashedString(hashedUserPassword);
if(!validateHandler.validateUser(userId, userPassword)){ return; }
onlineUserServiceNotifier.updateOnlineUserService(userId);
clientDataSender.sendCustomizedLoginMessage(userId);
clientDataSender.sendOneTimeOffer(userId);
}
}
DecryptHandler:
public class DecryptHandler implements IDecryptHandler {
public String decryptHashedString(String hashedString){
String userId = "";
//TODO Decrypt hashed string for 150 lines of code...
return userId;
}
}
public interface IDecryptHandler {
String decryptHashedString(String hashedString);
}
ValidateHandler:
public class ValidateHandler implements IValidateHandler {
public boolean validateUser(String userId, String userPassword){
//validate for 100 lines of code...
List<String> userIdList = getUserIdList();
if(!isUserIdValid(userId,userIdList)){return false;}
if(!isPasswordCorrect(userId,userPassword)){return false;}
return true;
}
private List<String> getUserIdList() {
List<String> userIdList = new ArrayList<>();
//TODO: Add implementation details
return userIdList;
}
private boolean isPasswordCorrect(String userId, String userPassword)
{
boolean isValidated = false;
//TODO: Add implementation details
return isValidated;
}
private boolean isUserIdValid(String userId, List<String> userIdList)
{
boolean isValidated = false;
//TODO: Add implementation details
return isValidated;
}
}
Important thing to note here is that the interfaces () only has to include the methods used by other classes. So IValidateHandler looks as simple as this:
public interface IValidateHandler {
boolean validateUser(String userId, String userPassword);
}
OnlineUserServiceNotifier:
public class OnlineUserServiceNotifier implements
IOnlineUserServiceNotifier {
public void updateOnlineUserService(String userId){
//TODO updateOnlineUserService for 100 lines of code...
}
}
public interface IOnlineUserServiceNotifier {
void updateOnlineUserService(String userId);
}
ClientDataSender:
public class ClientDataSender implements IClientDataSender {
public void sendCustomizedLoginMessage(String userId){
//TODO sendCustomizedLoginMessage for 50 lines of code...
}
public void sendOneTimeOffer(String userId){
//TODO sendOneTimeOffer for 100 lines of code...
}
}
Since both methods are accessed in LoginHandler, interface has to include both methods:
public interface IClientDataSender {
void sendCustomizedLoginMessage(String userId);
void sendOneTimeOffer(String userId);
}
There are really two topics here:
Given a God class, how its members be rationally partitioned into subsets? The fundamental idea is to group elements by conceptual coherency (often indicated by frequent co-usage in client modules) and by forced dependencies. Obviously the details of this are specific to the system being refactored. The outcome is a desired partition (set of groups) of God class elements.
Given a desired partition, actually making the change. This is difficult if the code base has any scale. Doing this manually, you are almost forced to retain the God class while you modify its accessors to instead call new classes formed from the partitions. And of course you need to test, test, test because it is easy to make a mistake when manually making these changes. When all accesses to the God class are gone, you can finally remove it. This sounds great in theory but it takes a long time in practice if you are facing thousands of compilation units, and you have to get the team members to stop adding accesses to the God interface while you do this. One can, however, apply automated refactoring tools to implement this; with such a tool you specify the partition to the tool and it then modifies the code base in a reliable way. Our DMS can implement this Refactoring C++ God Classes and has been used to make such changes across systems with 3,000 compilation units.
This is more a solution / work around than an actual question. I'm posting it here since I couldn't find this solution on stack overflow or indeed after a lot of Googling.
The Problem:
I have an MVC 3 webapp using EF 4 code first that I want to write unit tests for. I'm also using NCrunch to run the unit tests on the fly as I code, so I'd like to avoid backing onto an actual database here.
Other Solutions:
IDataContext
I've found this the most accepted way to create an in memory datacontext. It effectively involves writing an interface IMyDataContext for your MyDataContext and then using the interface in all your controllers. An example of doing this is here.
This is the route I went with initially and I even went as far as writing a T4 template to extract IMyDataContext from MyDataContext since I don't like having to maintain duplicate dependent code.
However I quickly discovered that some Linq statements fail in production when using IMyDataContext instead of MyDataContext. Specifically queries like this throw a NotSupportedException
var siteList = from iSite in MyDataContext.Sites
let iMaxPageImpression = (from iPage in MyDataContext.Pages where iSite.SiteId == iPage.SiteId select iPage.AvgMonthlyImpressions).Max()
select new { Site = iSite, MaxImpressions = iMaxPageImpression };
My Solution
This was actually quite simple. I simply created a MyInMemoryDataContext subclass to MyDataContext and overrode all the IDbSet<..> properties as below:
public class InMemoryDataContext : MyDataContext, IObjectContextAdapter
{
/// <summary>Whether SaveChanges() was called on the DataContext</summary>
public bool SaveChangesWasCalled { get; private set; }
public InMemoryDataContext()
{
InitializeDataContextProperties();
SaveChangesWasCalled = false;
}
/// <summary>
/// Initialize all MyDataContext properties with appropriate container types
/// </summary>
private void InitializeDataContextProperties()
{
Type myType = GetType().BaseType; // We have to do this since private Property.Set methods are not accessible through GetType()
// ** Initialize all IDbSet<T> properties with CollectionDbSet<T> instances
var DbSets = myType.GetProperties().Where(x => x.PropertyType.IsGenericType && x.PropertyType.GetGenericTypeDefinition() == typeof(IDbSet<>)).ToList();
foreach (var iDbSetProperty in DbSets)
{
var concreteCollectionType = typeof(CollectionDbSet<>).MakeGenericType(iDbSetProperty.PropertyType.GetGenericArguments());
var collectionInstance = Activator.CreateInstance(concreteCollectionType);
iDbSetProperty.SetValue(this, collectionInstance,null);
}
}
ObjectContext IObjectContextAdapter.ObjectContext
{
get { return null; }
}
public override int SaveChanges()
{
SaveChangesWasCalled = true;
return -1;
}
}
In this case my CollectionDbSet<> is a slightly modified version of FakeDbSet<> here (which simply implements IDbSet with an underlying ObservableCollection and ObservableCollection.AsQueryable()).
This solution works nicely with all my unit tests and specifically with NCrunch running these tests on the fly.
Full Integration Tests
These Unit tests test all the business logic but one major downside is that none of your LINQ statements are guaranteed to work with your actual MyDataContext. This is because testing against an in memory data context means you're replacing the Linq-To-Entity provider but a Linq-To-Objects provider (as pointed out very well in the answer to this SO question).
To fix this I use Ninject within my unit tests and setup InMemoryDataContext to bind instead of MyDataContext within my unit tests. You can then use Ninject to bind to an actual MyDataContext when running the integration tests (via a setting in the app.config).
if(Global.RunIntegrationTest)
DependencyInjector.Bind<MyDataContext>().To<MyDataContext>().InSingletonScope();
else
DependencyInjector.Bind<MyDataContext>().To<InMemoryDataContext>().InSingletonScope();
Let me know if you have any feedback on this however, there are always improvements to be made.
As per my comment in the question, this was more to help others searching for this problem on SO. But as pointed out in the comments underneath the question there are quite a few other design approaches that would fix this problem.