Methods for Adding Data to Mock DBs in C# Unit Tests - c#

This post is meant to be more a discussion-starter, as I am somewhat new to unit testing and TDD.
I am currently writing some unit tests for a .NET process that interacts with several databases, and am using mock database contexts in an attempt to cover different edge cases within my tests, verify exception handling in the program itself, among other things. That being said, some of my unit tests use valid data, while others do not.
I am looking for feedback in terms of suggested best practices when adding valid/fake data to your mock database contexts. I've seen people do this a number of ways (e.g. - implement repository pattern, adding mock data to .csv files and making them part of the project, etc...).
I'm currently thinking about using a repository pattern for adding Survey objects to the Surveys table in my target DB.
First off, I've got the interface:
public interface ISurveyRepository
{
IQueryable<Survey> SurveySeries { get; }
}
This is implemented both for the mocking fake/valid data repositories as needed by unit tests
class FakeSurveyRepository : ISurveyRepository
{
private static IQueryable<Survey> fakeSurveySeries = new List<Survey> {
new Survey { id = 1, SurveyName="NotValid1", SurveyData="<data>fake</data>"},
new Survey { id = 2, SurveyName="NotValid2", SurveyData="<data>super fake</data>"},
.........,
new Survey {id = 10, SurveyName="NotValid10", SurveyData="<data>the fakest</data>" }
}.AsQueryable();
public IQueryable<Survey> SurveySeries
{
get { return fakeSurveySeries; }
}
}
// RealSurveyRepository : ISurveyRepository is similar to this, but with "good" data
I then have a class to consume this data for either fake/valid data by being passed a reference to the series in the constructor:
public class SurveySeriesProcessor
{
private ISurveyRepository surveyRepository;
public SurveySeriesProcessor( ISurveyRepository surveyRepository )
{
this.surveyRepository = surveyRepository;
}
public IQueryable<Survey> GetSurveys()
{
return surveyRepository.SurveySeries
}
}
And can then approach using these objects in my tests such as:
[TestClass]
public class SurveyTests
{
[TestMethod]
WhenInvalidSurveysFound_SurveyCopierThrowsInvalidSurveyDataErrorForEach()
{
// create mocking DB context and add fake data
var contextFactory = new ContextFactory( ContextType.Mocking );
var surveySeriesProcessor = new SurveySeriesProcessor( new FakeSurveyRepository() );
foreach(Survey surveyRecord in surveySeriesProcessor.GetSurveys() )
{
contextFactory.TargetDBContext.Surveys.AddObject( surveyRecord );
}
// instantiate object being tested and run it against fake test data
var testSurveyCopier = new SurveyCopier( contextFactory );
testSurveyCopier.Start();
// test behavior
List<ErrorMessage> errors = testSurveyCopier.ErrorMessages;
errors.Count.ShouldEqual( surveySeriesProcessor.GetSurveys().Count );
foreach(ErrorMessage errMsg in errors)
{
errMsg.ErrorCode.ShouldEqual(ErrorMessage.ErrorMessageCode.InvalidSurveyData);
}
}
}
NOTE: I realize that in the example code provided I don't necessarily need to make the classes implementing ISurveyRepository return the series as an IQueryable<Survey> (they could very well be List<Survey>). However, I am going to extend the functionality of the interface and these classes in the future to filter out the fake/valid series based on certain criteria added to LINQ queries, which is why I made the repositories implement IQueryable<>. This is mock-up code designed to convey the basic principles of what I'm thinking.
With all of this in mind, what I'm asking is:
Do you have any suggestions in terms of alternative approaches I could take in such scenarios?
What methods have you employed in the past, what did you like/not like about them? Which have you found were the easiest to maintain?
Given what I've posted, do you notice flaws in my general approach to unit testing? Sometimes I feel as though I write unit tests that attempt to cover too much ground instead of being concise, elegant, and to-the-point.
This is meant to be somewhat of an open discussion. Please keep in mind, this is the first set of unit tests I've ever written (I've read a decent amount of literature on the subject, however).

I think you're on a good track.
Personally, in the same situation, if I were dealing with a repository style pattern,
public interface IRepository<T>
{
IEnumerable<T> GetAll();
}
public class PonyRepository : IRepository<Pony>
{
IEnumerable<Pony> GetAll();
}
To actually supply me the data I need, I generally create a TestObjects or TestFakes class to supply the required data on-demand.
public class FakeStuff
{
public static IEnumerable<Pony> JustSomeGenericPonies(int numberOfPonies)
{
// return just some basic list
return new List<Pony>{new Pony{Colour = "Brown", Awesomeness = AwesomenessLevel.Max}};
// or could equally just go bananas in here and do stuff like...
var lOfP = new List<Pony>();
for(int i = 0; i < numberOfPonies; i++)
{
var p = new Pony();
if(i % 2 == 0)
{
p.Colour = "Gray";
}
else
{
p.Colour = "Orange";
}
lOfP.Add(p);
}
return lOfP;
}
}
And test with this as such:
[Test]
public void Hello_I_Want_to_test_ponies()
{
Mock<IRepository<Pony> _mockPonyRepo = new Mock<IRepository<Pony>>();
_mockPonyRepo.SetUp(m => m.GetAll()).Returns(FakeStuff.JustSomeGenericPonies(50));
// Do things that test using the repository
}
So this delivers reusability of the fake data, by keeping it out of the repository and in a place of it's own, meaning I can call this list of ponies anywhere a test requires a list of ponies, not just where a repository is involved.
If I need specific data for a specific testcase, i'll implement something like you had, but be a bit more explicit about what that particular Fake repository is for:
public class FakePonyRepositoryThatOnlyReturnsBrownPonies : IRepository<Pony>
{
private List<Pony> _verySpecificAndNotReusableListOfOnlyBrownPonies = new List....
public IEnumerable<Pony> GetAll()
{
return _verySpecificAndNotReusableListOfOnlyBrownPonies;
}
}
public class FakePonyRepositoryThatThrowsExceptionFromGetAll : IRepository<Pony>
{
public IEnumerable<Pony> GetAll()
{
throw new OmgNoPoniesException();
}
}
You mentioned CSV files as well - this could be viable (have used XML in the past), but I'd argue that holding fake data in a CSV or XML is just a worse version of keeping data in a localised DB using SQL CE or some equivalent. However, both of those are less maintainable and, crucially, in terms of unit tests, slower than using in-memory fake objects. I personally wouldn't use a file-based approach anymore unless I was specifically testing serialization or IO or something.
Hope there's something useful among all that lot...

Related

Good To Use Classes to Create Dummy Data for Unit Tests?

I am trying to do some unit tests and I need dummy data. Some of this data I need to have specific values, other will be just random.
I have for instance a "CreateProduct" method in my Service Layer and I am wondering if it is a good idea to use such methods instead of making a product by hand in my unit tests.
On the surface this seems like a good idea but I am worried maybe I will need to mocking or something to successfully get through that method.
The CreateProduct will try to save the product to the database but I have already a flag that will stop the save happening(used for unit of work scenario encase of rollbacks).
I am using EF 6-rc1 and mocking up the DataContext with moq and I was going to use AutoFixture but it does not work out of box for this secnario and I am starting to feel I am taking too much new tools on at once so maybe I should just do it manually for now.
It's hard to tell exactly what you are doing without a code example, but I sometimes use this implementation of an IDataSet that uses a List in memory. Typical usage would be something like:
using System.Data.Entity;
using System.Linq;
using Moq;
using NUnit.Framework;
namespace EFMock
{
internal interface IDataContext
{
IDbSet<DataItem> DataItems { get; set; }
}
class DataContext : DbContext, IDataContext
{
public IDbSet<DataItem> DataItems{ get; set; }
}
class DataItem
{
public int SomeNumber { get; set; }
public string SomeString { get; set; }
}
/* ----------- */
class DataUsage
{
public int DoSomething(IDataContext dataContext)
{
return dataContext.DataItems.Sum(x => x.SomeNumber);
}
}
/* ----------- */
[TestFixture]
class TestClass
{
[Test]
public void SomeTest()
{
var fakeDataItems = new [] {
new DataItem { SomeNumber = 1, SomeString = "One" },
new DataItem { SomeNumber = 2, SomeString = "Two" }};
var mockDataContext = new Mock<IDataContext>();
mockDataContext.SetupGet(x => x.DataItems).Returns(new FakeDbSet<DataItem>(fakeDataItems));
var dataUsage = new DataUsage();
var result = dataUsage.DoSomething(mockDataContext.Object);
Assert.AreEqual(2, result);
}
}
}
I also have a NuGet package named "FakeO" that you can use to create some fake objects, where some data is a specific value and some is random:
var fakeDataItems = FakeO.Create.Fake<DataItem>(10, // create an IEnumerable of 10 items
x => x.SomeNumber = FakeO.Number.Next(), // set to a random number
x => x.SomeString = "Always This String"); // set to a specific string
One thing to keep in mind with this kind of testing is that using an IQueryable against a List will use Linq2Objects and not Linq2Entities, so results of some Linq queries will be different.
If you want to Unit Test something, you'll just want to test the unit. If you use a method in the servicelayer to generate some fake data, the unit test is not only testing the unit under test, but also the method in the service layer.
So the answer to your question: no, it is not a good idea to use the service layer to dummy data

Best practices for using Mocks in TDD (MOQ)

I am new to using Mocks. But what are it's main purposes? I'm going to start by using Moq to test my application (and NUnit).
For example, I have code that does things like this:
My webpage code behind:
public partial class MyWebpage
{
protected string GetTitle(string myVar)
{
return dataLayer.GetTitle(myVar);
}
}
My data access layer:
public class DataLayer
{
public string GetTitle(string myVar)
{
// Create the query we want
string query = "SELECT title FROM MyTable " +
"WHERE var = #myVar";
//ENTER PARAMETERS IN HERE
// Now return the result to the view
return this.dataProvider.ExecuteMySelectQuery(
dr =>
{
//DELEGATE DATA READER PASSED IN AND TITLE GETS RETURNED
},
query,
parameters);
}
}
My data provider talks and interacts directly with the db:
public class DataProvider
{
public T ExecuteMySelectQuery<T>(Func<IDataReader, T> getMyResult, string selectQuery, Dictionary parameters)
{
//RUNS AND RETURNS THE QUERY
}
}
What's the best way to test all of this?
If you want to test the layers separately, you would need to create interfaces for your DataProvider and DataLayer classes that expose the methods that you want to Mock. Then you can use a mocking framework - NSubstitute is very good, less code to write to create the mocks - to mock out the calls to the dependent classes, leaving you to test the code within that specific unit
public interface IDataProvider
{
T ExecuteMySelectQuery<T>(Func<IDataReader, T> getMyResult, string selectQuery, Dictionary parameters);
}
public interface IDataLayer
{
string GetTitle(string myVar);
}
public class DataLayer
{
private IDataProvider dataProvider;
public DataLayer(IDataProvider dataProvider)
{
this.dataProvider = dataProvider;
}
}
Then, in your test code, you create mocks instead of real objects and pass those into the constructor when you instantiate your test objects. To test the DataLayer:
[Test]
public void WhenRetievingTitleFromDataStore_ThenDataLayerReturnsTitle()
{
var title = "Title";
var dataProviderMock = new Mock<IDataProvider>(MockBehavior.Strict);
dataProviderMock.Setup(x => x.ExecuteMySelectQuery(<parameters>)).Returns(title);
var dataLayer = new DataLayer(dataProviderMock.Object);
Assert.That(dataLayer.GetTitle(It.IsAny<string>(), Is.EqualTo(title));
}
The only thing that can go wrong with that is the DB call (the query or the returned result is of wrong data types). That can't be mocked. You need to do integration tests and not unit tests.
Typically you only mock to be able to test logic in the code. You should for instance test so that the data mapper (this.dataProvider.ExecuteMySelectQuery) works as defined. but that's of the scope of the code in question.
Update
So you got the following classes:
public class DataLayer
{
public string GetTitle(string myVar)
{
// Create the query we want
string query = "SELECT title FROM MyTable " +
"WHERE var = #myVar";
//ENTER PARAMETERS IN HERE
// Now return the result to the view
return this.dataProvider.ExecuteMySelectQuery(
dr =>
{
//DELEGATE DATA READER PASSED IN AND TITLE GETS RETURNED
},
query,
parameters);
}
}
public class DataProvider
{
public T ExecuteMySelectQuery<T>(Func<IDataReader, T> getMyResult, string selectQuery, Dictionary parameters)
{
//RUNS AND RETURNS THE QUERY
}
}
If we examine the ExecuteMySelectQuery we can see that the DataLayer class is dependent of how the types that the database returns since the DataProvider just ease the query execution. One could say that it's an addon on top of ADO.NET.
That also means that you can never guarantee that DataLayer return what's promised without involving the database. Let's for instance assume that the table in the database has a column called title but someone managed to use the int data type instead.
The things that can go wrong are
The query is incorrect
The schema in the database is incorrect (wrong column names, data types etc)
The mapping
None of those errors can be detected nor tested with the help of a mock.
If you on the other hand use the DataLayer clas in another class you can of course mock it. Because the DataLayer class itself is a complete abstraction. That means that the callers of the class doesn't have to be aware of anything beneath it. Hence mocking is perfectly fine.

Testing Entity Framework Data by Hitting the Database

I am trying to test my real data by actually hitting the database. I am actually testing my Repository classes. Here is an example of what I am doing;
/// <summary>
/// Summary description for Country
/// </summary>
[TestClass]
public class Country {
public Country() {
_countryRepo = new CountryRepository();
}
private ICountryRepository _countryRepo;
[TestMethod]
public void db_should_return_at_least_one_country_as_approved_all() {
//Act
var model = _countryRepo.GetAll();
//Assert
Assert.IsTrue(model.Count() >= 1);
}
[TestMethod]
public void db_should_return_at_least_one_country_as_approved_true() {
//Act
var model = _countryRepo.GetAll(ApprovalStatus.Approved);
//Assert
Assert.IsTrue(model.Count() >= 1);
}
[TestMethod]
public void db_should_return_Turkey_as_country_name_by_id() {
//Act
var model = _countryRepo.GetSingle(1000);
//Assert
Assert.AreEqual<string>("Turkey", model.CountryName);
}
[TestMethod]
public void db_should_return_Turkey_as_country_name_by_countryISO3166Code() {
//Act
var model = _countryRepo.GetSingle("TR");
//Assert
Assert.AreEqual<string>("Turkey", model.CountryName);
}
[TestMethod]
public void db_should_return_Turkey_as_country_name_by_GUID() {
//Act
var model = _countryRepo.GetSingle(Guid.Parse("9AF174A6-D0F7-4393-AAAD-B168BADEDB30"));
//Assert
Assert.AreEqual<string>("Turkey", model.CountryName);
}
}
This works pretty well for my needs but wondering if I am doing it right by the book. Is there any other patterns that I really should be following here. I do not want to fake my data, my real intense here is to test my DAL and real production data.
Your tests will fail if someone else (or even you) go to your database and create a new approved country or change your country name. You are going to think: "WTH is wrong with my repository, why is it not working as expected?" But yeah, the problem isn't with the repository.
When I write tests that hit the database I like to create the DB and load default values at startup and destroy then all right after that. I'm not sure if this is the best alternative, but it works pretty well. The problem with this approach is that it's slower and there is more to code.
For the requirement at hand, i.e. data that is really static, and should not be tampered with, I'd say this is a valid approach.
I would recommend to write data-driven tests however, instead of repeating the same test case for each country.
You should use static database just for testing and your methods testing GetAll should assert against real expected count. How do you know that it really returned what you expected if you just assert that it returned at least one record? You should even go through result set and test that all records satisfy the condition (but it is usually used for more complicated conditions).

Domain modelling - Implement an interface of properties or POCO?

I'm prototyping a tool that will import files via a SOAP api to an web based application and have modelled what I'm trying to import via C# interfaces so I can wrap the web app's model data in something I can deal with.
public interface IBankAccount
{
string AccountNumber { get; set; }
ICurrency Currency { get; set; }
IEntity Entity { get; set; }
BankAccountType Type { get; set; }
}
internal class BankAccount
{
private readonly SomeExternalImplementation bankAccount;
BankAccount(SomeExternalImplementation bankAccount)
{
this.bankAccount = bankAccount;
}
// Property implementations
}
I then have a repository that returns collections of IBankAccount or whatever and a factory class to create BankAccounts for me should I need them.
My question is, it this approach going to cause me a lot of pain down the line and would it be better to create POCOs? I want to put all of this in a separate assembly and have a complete separation of data access and business logic, simply because I'm dealing with a moving target here regarding where the data will be stored online.
This is exactly the approach I use and I've never had any problems with it. In my design, anything that comes out of the data access layer is abstracted as an interface (I refer to them as data transport contracts). In my domain model I then have static methods to create business entities from those data transport objects..
interface IFooData
{
int FooId { get; set; }
}
public class FooEntity
{
static public FooEntity FromDataTransport(IFooData data)
{
return new FooEntity(data.FooId, ...);
}
}
It comes in quite handy where your domain model entities gather their data from multiple data contracts:
public class CompositeEntity
{
static public CompositeEntity FromDataTransport(IFooData fooData, IBarData barData)
{
...
}
}
In contrast to your design, I don't provide factories to create concrete implementations of the data transport contracts, but rather provide delegates to write the values and let the repository worry about creating the concrete objects
public class FooDataRepository
{
public IFooData Insert(Action<IFooData> insertSequence)
{
var record = new ConcreteFoo();
insertSequence.Invoke(record as IFooData);
this.DataContext.Foos.InsertOnSubmit(record); // Assuming LinqSql in this case..
return record as IFooData;
}
}
usage:
IFooData newFoo = FooRepository.Insert(f =>
{
f.Name = "New Foo";
});
Although a factory implementation is an equally elegant solution in my opinion. To answer your question, In my experience of a very similar approach I've never come up against any major problems, and I think you're on the right track here :)

Using the MVP for a composite structured object model

(Edited a lot) I've got some classes with Abstracts Members. The concrete type of the abstract members is to be determined at the class instanciation, based on the user's input. However, the second member's concrete type might depend on the first member.
I'm trying to do something keeping the MVP design pattern in mind. I taught about making the Presenter pass a delegate to the Model's Ctor, which he (the Ctor) would use to request the informations needed for the instanciation of the class. I'm not sure if it's a good idea. Here is what I wrote :
// In the Model :
public class Model
{
public E Element1;
public E Element2;
public Model(CustomCtor<ModelElement, IModelElement> GetModelElement)
{
this.Element1 = (E)GetModelElement(ModelElement.E, null);
this.Element2 = (E)GetModelElement(ModelElement.E, null);
//Element2 does not depend on Element1 in this case though.
}
}
public abstract class E : IModelElement { }
public class EA : E
{
public string Element1;
public EA(string Element1) { this.Element1 = Element1; }
}
public class EB : E
{
public int Element1;
public EB(int Element1) { this.Element1 = Element1; }
}
public interface IModelElement { }
public enum ModelElement { E, EA, EB }
// In the Presenter :
public class Presenter
{
View.View view1;
public Presenter() { }
public void SetView(View.View view) { this.view1 = view; }
public Model.Model MakeModel()
{
CustomCtor<ModelElement, IModelElement> GetModelElement = new CustomCtor<ModelElement, IModelElement>(GetModelElement<ModelElement, IModelElement>);
return new Model.Model(GetModelElement);
}
private Model.IModelElement GetModelElement<ModelElement, Tout>(Model.ModelElement ME, object obj)
{
switch (ME)
{
case Model.ModelElement.E:
return MakeE();
// One case per Model.ModelElement
default:
throw new Exception("ModelElement not implemented in the Presenter.");
}
return default(Model.IModelElement);
}
private E MakeE()
{
switch (view1.AskEType())
{
case 1:
return MakeEA();
case 2:
return MakeEB();
default:
throw new Exception();
}
}
private EA MakeEA() { return new EA(view1.AskString("EA.Element1 (String)")); }
private EB MakeEB() { return new EB(view1.AskInt("EB.Element1 (Int)")); }
}
// Shared to the Model and the Presenter :
public delegate TOut CustomCtor<EnumType, TOut>(EnumType Enum, object Params) where EnumType : struct;
// In the View :
public class View
{
public int AskEType()
{
Console.WriteLine(string.Format("Type of E : EA(1) or EB(2)?"));
return int.Parse(Console.ReadLine());
}
public string AskString(string Name)
{
Console.Write(string.Format("{0} ? ", Name));
return Console.ReadLine();
}
public int AskInt(string Name)
{
Console.Write(string.Format("{0} ? ", Name));
return int.Parse(Console.ReadLine());
}
}
//In the Program :
class Program
{
static void Main(string[] args)
{
View.View view1 = new View.View();
Presenter.Presenter presenter1 = new Presenter.Presenter();
presenter1.SetView(view1);
presenter1.MakeModel();
}
}
Does that make sense? Is there a name for the thing I'm trying to do? (beside "A weird thing")
Are you aware of a design pattern I should read on?
I taught about mixing the Builder design pattern with the MVP, but I'm not sure how I'd do that.
Thanks
I am not certain this is what your asking about, but I am assuming you are trying to keep your view isolated from your model. If that is indeed what you are trying to do, I think your taking a much too complicated approach. The view is simply a presentation and feedback medium. It really does not need to know anything about models, it can be designed to make use of simple data in a property bag of some kind. This creates a cleaner separation, however, it often makes rendering data and maintaining the view a lot harder as well.
First question I would ask is, is it REALLY worth it to expend so much effort keeping your view entirely isolated from your model? What are you really gaining by having an absolute separation?
If you do indeed need a separation, make sure you understand the roles of view and presenter. The view is dumb...it knows nothing and does nothing. It presents information and forms. The browser issues commands requested by the user. The presenter handles commands, and directs data to its view. The concept of "presenter asking the view" for anything is generally incorrect. The presenter should be handling the command (http request) directly, so it should know any and all details about a particular command. When it comes time to render the view, the presenter should provide any data to the view in whatever form the view needs it to be in. If you do not want your view to know about your object model, then either create properties on the view itself to contain the data, or create a view-specific model that encapsulates the data required.
EDIT:
I've just read your update. I think I understand your problem a bit better now. First off, before I go any farther, you need to reorganize responsibilities a little bit. Currently, you have it such that your view is responsible for handling input. That is a bit of a corruption of the purpose and concept of a 'view'. In both MVP and MVC, the view is supposed to be as "dumb" as possible, and really should not be responsible for processing anything...commands, actions, input, etc. should all be the responsibility of the Controller or Presenter.
Seeing that your view is actually a console application, not a web forms application (which was my original assumption), I think that MVC might actually be a better fit for your needs. MVP is a good solution for getting around the deficiencies of ASP.NET WebForms, but it is not as powerful or successful at helping separate concerns as MVC is. I would look into implementing an MVC pattern, which was originally designed for console type applications. The controller becomes the central input handler, which then issues commands to command handlers and your model. The view would then be pure and true to form...only rendering information and nothing else.
If there is some reason why you cannot use an MVC approach, which I think would be ideal, and must use MVP, I can offer more advice on how you could fix your current implementation. However, I would strongly suggest looking into using MVC, as that patterns was originally designed to solve the very problem you are trying to solve...in console applications.

Categories

Resources