Entity Framework Integration tests DropCreateDatabaseAlways not clearing database between test - unit-testing

I am writing a set of integration tests (Unit tests with MS Test which test that Entity Framework 4.2 is persisting all classes correctly to the database).
When I run all tests one by one they all work fine. When I run them in a group - some of them fail as the wrong number of objects are returned - it would seem that the db is being cleaned down once at the start of the tests and not in between each test - even though I can see a new context being created and then disposed of for each test
Any Ideas?
public class EmptyDataInitializer : DropCreateDatabaseAlways<myContext>
{
protected override void Seed(myContext db)
{
//Do Nothing Create Empty Database
db.SaveChanges();
base.Seed(db);
}
}
A Cut down version of the unit/integration Tests
[TestClass]
public class PersistanceTests
{
//Creating two instances of our Repository so that we can make sure that we are reading from our database rather than in-memory
private myContext _db;
private myContext _dbResults;
private readonly ISettings _configSettings;
public PersistanceTests()
{
_configSettings = MockRepository.GenerateStub<ISettings>();
_configSettings.ConnectionString = "data source=.;initial catalog=myContext_Test; Integrated Security=SSPI; Pooling=false";
Database.SetInitializer(new EmptyDataInitializer());
}
//This is called a single time after the last test has finished executing
[TestCleanup]
public void TearDownTest()
{
_db.Dispose();
_db = null;
_dbResults.Dispose();
_dbResults = null;
}
//This is called each time prior to a test being run
[TestInitialize]
public void SetupTest()
{
_db = new myContext(_configSettings);
_dbResults = new myContext(_configSettings);
// This forces the database to initialise at this point with the initialization data / Empty DB
var count = _db.Accounts.Count();
var resultCount = _dbResults.Accounts.Count();
if (count != resultCount) throw new InvalidOperationException("We do not have a consistant DB experiance.");
}
[TestMethod]
public void OrganisationPersistanceTest()
{
// Arrange
var apple = new Organisation { Name = "Apple" };
_db.Organisations.Add(apple);
// Act
_db.SaveChanges();
var organisationsCount = _dbResults.Organisations.Count();
var organisationsAppleCount = _dbResults.Organisations.Where(a => a.Id == apple.Id).Count();
var result = _dbResults.Organisations.FirstOrDefault(a => a.Id == apple.Id);
// Assert
Assert.IsTrue(organisationsCount == 1, string.Format("Organisations Count Mismatch - Actual={0}, Expected={1}", organisationsCount, 1));
Assert.IsTrue(organisationsAppleCount == 1, string.Format("Apple Organisations Count Mismatch - Actual={0}, Expected={1}", organisationsAppleCount, 1));
Assert.IsNotNull(result, "Organisations Result should not be null");
Assert.AreEqual(result.Name, apple.Name, "Name Mismatch");
}
//A Unit test
[TestMethod]
public void OrganisationWithNumberOfPeople_PersistanceTest()
{
// Arrange
var person = new Person { Firstname = "Bea" };
var anotherPerson = new Person { Firstname = "Tapiwa" };
var apple = new Organisation { Name = "Apple" };
apple.AddPerson(person);
apple.AddPerson(anotherPerson);
_db.Organisations.Add(apple);
// Act
_db.SaveChanges();
var organisationsCount = _dbResults.Organisations.Count();
var organisationsAppleCount = _dbResults.Organisations.Where(a => a.Id == apple.Id).Count();
var result = _dbResults.Organisations.FirstOrDefault(a => a.Id == apple.Id);
var peopleCountInOrganisation = result.People.Count();
// Assert
Assert.IsTrue(organisationsCount == 1, string.Format("Organisations Count Mismatch - Actual={0}, Expected={1}", organisationsCount, 1));
Assert.IsTrue(organisationsAppleCount == 1, string.Format("Apple Organisations Count Mismatch - Actual={0}, Expected={1}", organisationsAppleCount, 1));
Assert.IsNotNull(result, "Organisations Result should not be null");
Assert.AreEqual(result.People.Count, peopleCountInOrganisation, "People count mismatch in organisation Apple - Actual={0}, Expected={1}", peopleCountInOrganisation, 2);
Assert.AreEqual(result.Name, apple.Name, "Name Mismatch");
}
}
Stepping through the tests I can see the SetupTest and TearDownTest methods being called but I it does not seem to clean down the database between tests.

Okay even Better answer - add a database.Initialize(force: true);
into the TestInitialize method.
[TestInitialize]
public void SetupTest()
{
_db = new myContext(_configSettings);
_db.Database.Initialize(force: true);
_dbResults = new myContext(_configSettings);
// This forces the database to initialise at this point with the initialization data / Empty DB
var count = _db.Accounts.Count();
var resultCount = _dbResults.Accounts.Count();
if (count != resultCount) throw new InvalidOperationException("We do not have a consistant DB experiance.");
}

I use a helper for doing this kind of tasks:
public abstract class TestingHelper
{
public static void ClearDatabase()
{
DatabaseContext myDbContext = new DatabaseContext();
myDbContext.Database.Delete();
myDbContext.Database.Create();
//FillDatabase(lawyers); //<- OPTIONAL if you want to add rows to any type tables
}
}
And then use it in the SetUp of your test:
[SetUp]
public void MyTests_SetUp()
{
TestingHelper.ClearDatabase();
}

Related

How to write test case for relational database operations using xunit

I am using InMemoryDatabase for writing testcases, but when I want to test relational database operations(Insert/Update) I could not able to use InMemoryDatabase.
If I am using InMemoryDatabase I am getting an error like
System.InvalidOperationException: 'Relational-specific methods can only be used when the context is using a relational database provider.'
Is there any way to test relational database operations(Insert/Update) without touching the development or production database?
This is the repository class which uses the relational db operations
public bool UpdateOrInsert(Model model, Details details = null)
{
//_context is SqlDbContext
using (var transaction = _context.Database.BeginTransaction())
{
try
{
if(details.Id > 0)
{
//Update details;
_context.SaveChanges();
}
else
{
//Insert details;
_context.SaveChanges();
}
if(model.Id > 0)
{
//Update model;
_context.SaveChanges();
}
else
{
//Insert model;
_context.SaveChanges();
}
transaction.Commit();
return true;
}
catch(Exception ex)
{
transaction.Rollback();
throw;
}
}
}
How can we write unit test for this method without touching the real database? Is there any way?
The testcase I used to test this method throws the above error.
[Fact]
public void CheckTest()
{
DbContextOptions<SqlDbContext> _options;
_options = new DbContextOptionsBuilder<SqlDbContext>()
.UseInMemoryDatabase(databaseName: "DbName1")
.Options;
using (var context = new SqlDbContext(_options))
{
context.Model.Add(_model);//_model= sample model object
context.Details.Add(_details);//_details = sample details object
context.SaveChanges();
var cls = new ClassName();
var result = cls.UpdateOrInsert(_model,_details);
Assert.Assert.IsType<Bool>(result);
}
}
If I use the following way to check, it will be possible to update the original database.
[Fact]
public void CheckTest()
{
var connectionString = #"Data Source = *****; Initial Catalog = ******; uid = ****; Pwd = ******";
DbContextOptions<SqlDbContext> _sqlOptions = new DbContextOptionsBuilder<SqlDbContext>()
.UseSqlServer(connectionString)
.ConfigureWarnings(x => x.Ignore(InMemoryEventId.TransactionIgnoredWarning))
.Options;
using (var context = new SqlDbContext(_sqlOptions))
{
var cls = new ClassName();
var result = cls.UpdateOrInsert(_model,_details);
Assert.Assert.IsType<Bool>(result);
}
}
Do we have any other way to write test case for the method - UpdateOrInsert without touching the relational database?
Is it possible to test via InMemmoryDatabase?
Please help

How to Mock QueryMultiple using Moq.Dapper

I am writing unit test cases and I am successful in writing unit test case for Query. But I am failing to write unit test case for QueryMultiple.
For Query I am writing like this:
IEnumerable<ClientTestPurpose> fakeTestPurposes = new
List<ClientTestPurpose>()
{
new ClientTestPurpose { PurposeID = 1, PurposeName = "Test Purpose name1"},
new ClientTestPurpose { PurposeID = 1, PurposeName = "Test Purpose name2"},
new ClientTestPurpose { PurposeID = 1, PurposeName = "Test Purpose name3"}
};
_mock.SetupDapper(x => x.Query<ClientTestPurpose>(It.IsAny<string>(), null, null, true, null, null)).Returns(fakeTestPurposes);
var result = _libraryRepository.TestPurposes(clientModal.Id);
Assert.IsNotNull(result);
Assert.AreEqual(result.Count(), fakeTestPurposes.Count());
How to write for QueryMultiple:
using (var multi = _db.QueryMultiple(spName, spParams, commandType: CommandType.StoredProcedure))
{
var totals = multi.Read<dynamic>().FirstOrDefault();
var aggregates = multi.Read<StatusModel>();
var scripts = multi.Read<LibraryItemModel>();
var runs = multi.Read<RunSummaryModel>();
var filteredTotals = multi.Read<dynamic>().FirstOrDefault();
}
Apparently you use Moq.Dapper extenstions. Here is the code of SetupDapper and SetupDapperAsync method:
public static ISetup<IDbConnection, TResult> SetupDapper<TResult>(this Mock<IDbConnection> mock, Expression<Func<IDbConnection, TResult>> expression)
{
MethodCallExpression body = expression.Body as MethodCallExpression;
if ((body != null ? body.Method.DeclaringType : (Type) null) != typeof (SqlMapper))
throw new ArgumentException("Not a Dapper method.");
string name = body.Method.Name;
if (name == "Execute")
return (ISetup<IDbConnection, TResult>) DbConnectionInterfaceMockExtensions.SetupExecute(mock);
if (name == "ExecuteScalar")
return DbConnectionInterfaceMockExtensions.SetupExecuteScalar<TResult>(mock);
if (name == "Query" || name == "QueryFirstOrDefault")
return DbConnectionInterfaceMockExtensions.SetupQuery<TResult>(mock);
throw new NotSupportedException();
}
public static ISetup<IDbConnection, Task<TResult>> SetupDapperAsync<TResult>(this Mock<IDbConnection> mock, Expression<Func<IDbConnection, Task<TResult>>> expression)
{
MethodCallExpression body = expression.Body as MethodCallExpression;
if ((body != null ? body.Method.DeclaringType : (Type) null) != typeof (SqlMapper))
throw new ArgumentException("Not a Dapper method.");
if (body.Method.Name == "QueryAsync")
return DbConnectionInterfaceMockExtensions.SetupQueryAsync<TResult>(mock);
throw new NotSupportedException();
}
As you can see Moq.Dapper supports mocking only for Execute, ExecuteScalar, Query and QueryAsync methods. Therefore you probably get NotSupportedException on trying to mock QueryMultiple. To mock DB behavior you probably need introduce another level of abstraction first, as #TrueWill said in a comments. Here is just an example of idea how it can be in your case:
[Test]
public void DoSomethingWithQueryTest()
{
// Arrange
IEnumerable<ClientTestPurpose> fakeTestPurposes = new
List<ClientTestPurpose>
{
new ClientTestPurpose { PurposeID = 1, PurposeName = "Test Purpose name1" },
new ClientTestPurpose { PurposeID = 1, PurposeName = "Test Purpose name2" },
new ClientTestPurpose { PurposeID = 1, PurposeName = "Test Purpose name3" }
};
var mock = new Mock<ILibraryRepository>();
mock.Setup(x => x.TestPurposes(It.IsAny<int>())).Returns(fakeTestPurposes);
var logicService = new SomeLogicService(mock.Object);
// Act
var result = logicService.DoSomethingWithQuery(1);
// Assert
Assert.IsNotNull(result);
Assert.AreEqual(result.Count(), fakeTestPurposes.Count());
}
[Test]
public void DoSomethingWithQueryMultipleTest()
{
// Arrange
SomeAggregate fakeTestPurposes = new SomeAggregate();
var mock = new Mock<ILibraryRepository>();
mock.Setup(x => x.TestQueryMultiple()).Returns(fakeTestPurposes);
var logicService = new SomeLogicService(mock.Object);
// Act
var result = logicService.DoSomethingWithQueryMultiple();
// Assert
Assert.IsNotNull(result);
}
public interface ILibraryRepository
{
IEnumerable<ClientTestPurpose> TestPurposes(int id);
SomeAggregate TestQueryMultiple();
}
public class LibraryRepository : ILibraryRepository
{
private readonly IDbConnection _db;
public LibraryRepository(IDbConnection db)
{
_db = db ?? throw new ArgumentNullException(nameof(db));
}
public IEnumerable<ClientTestPurpose> TestPurposes(int id)
{
return _db.Query<ClientTestPurpose>("SQL here", new { id }, null, true, null, null);
}
public SomeAggregate TestQueryMultiple()
{
string spName = "SQL here";
var spParams = new { Id = 1 };
using (var multi = _db.QueryMultiple(spName, spParams, commandType: CommandType.StoredProcedure))
{
return new SomeAggregate
{
totals = multi.Read<dynamic>().FirstOrDefault(),
aggregates = multi.Read<StatusModel>(),
scripts = multi.Read<LibraryItemModel>(),
runs = multi.Read<RunSummaryModel>(),
filteredTotals = multi.Read<dynamic>().FirstOrDefault()
};
}
}
}
public class SomeAggregate
{
public IEnumerable<dynamic> totals { get; set; }
public IEnumerable<StatusModel> aggregates { get; set; }
public IEnumerable<LibraryItemModel> scripts { get; set; }
public IEnumerable<RunSummaryModel> runs { get; set; }
public IEnumerable<dynamic> filteredTotals { get; set; }
}
/// <summary>
/// Example logic server, that just returns results from repository
/// </summary>
public class SomeLogicService
{
private readonly ILibraryRepository _repo;
public SomeLogicService(ILibraryRepository repo)
{
_repo = repo;
}
public IEnumerable<ClientTestPurpose> DoSomethingWithQuery(int id)
{
return _repo.TestPurposes(id);
}
public SomeAggregate DoSomethingWithQueryMultiple()
{
return _repo.TestQueryMultiple();
}
}
The main idea is to hide all DB specific thing behind the ILibraryRepository and move all logic that you need to test to some logic server, that will receive repository as dependency. In order code in repository should be simple, obvious, contains all DB specific logic: connection, transaction, command, object-relation mapping, etc. And you don't need to cover this code with unt tests. However you do cover code of SomeLogicService with unit tests, because this is what you really need to test. You see Dapper extension method are rather low-level abstraction, that doesn't hide details of working with DB, they are just helpers. Hope it helps.

In in moq unit test how to fix "Object reference not set to an instance of an object"

Okay I am trying to create a test that checks that my badge method actually added a badge to PlayersBadge. It works but I don't know how to test properly. The main issue is my understanding of moq.
This is my method it takes in a PlayerID, BadgeID, and GameID.
public bool Badge(int pID, int bID, int gID = 0)
{
var list = EliminationDbContext.PlayerBadges.Where(x => x.Badge.BadgeID.Equals(bID) && x.Player.PlayerID.Equals(pID));
if (list.Any() != true)
{
PlayerBadge b = new PlayerBadge { PlayerID = pID, BadgeID = bID, DateEarned = DateTime.Today, GameID = gID };
_RepoManager.PlayerBadges.Add(b);
_RepoManager.SaveDb();
return true;
}
return false;
}
Currently I am getting this error "Object reference not set to an instance of an object" I think it's because I'm not setting up a mock of PlayerBadge correctly but I'm not sure how to fix this
[Test]
public void testing()
{ //Arrange
var mock = new Mock<IRepoManager>();
var mockRequest = new Mock<PlayerBadge>();
var dManager = new TestMoq(mock.Object);
//set mockRequest to playerBadge
mockRequest.Setup(x => x.Badge.PlayerBadges.Add(badge));
//Act
//Object reference not set to an instance of an object on this line
dManager._RepoManager.PlayerBadges.Add(mockRequest.Object);
dManager._RepoManager.Badges.Badge(1, 2, 0);
Assert.That(dManager._RepoManager.PlayerBadges.GetPlayerBadges().Count() >= 1);
}

Where do you set the OrmLiteConfig.DialectProvider.NamingStrategy in a unit test?

I'm using both ORMLite and Dapper in a project and would like standardized on the naming conventions used by both ORMs. In order to do this I'd like to set the NamingStrategy as such:
OrmLiteConfig.DialectProvider.NamingStrategy = new OrmLiteNamingStrategyBase();
and a unit test to verify
public class BorrowerUnitTests : IDisposable
{
private readonly ServiceStackHost appHost;
public BorrowerUnitTests()
{
//Set ORMLite to work with columns like ColumnLikeThis
// OrmLiteConfig.DialectProvider.NamingStrategy = new OrmLiteNamingStrategyBase();
appHost = new BasicAppHost(typeof(BorrowerServices).Assembly)
{
ConfigureContainer = container =>
{
container.Register<IDbConnectionFactory>(c =>
new OrmLiteConnectionFactory(ConfigUtils.GetConnectionString("LoanOrigination:Default"), PostgreSqlDialect.Provider));
container.RegisterAutoWiredAs<Repository, IRepository>();
container.RegisterAutoWired<BorrowerDomainService>();
}
}
.Init();
}
public void Dispose()
{
appHost.Dispose();
}
[Fact]
public void TestPostMethod()
{
var service = appHost.Container.Resolve<BorrowerServices>();
BorrowerCreate request = new BorrowerCreate();
request.FirstName = "Orm";
request.LastName = "Lite";
request.Email = "ormlite#servicestack.net";
var response = service.Post(request);
Assert.True(response.Id > 0, "Id retured from POST cannot be zero");
}
[Fact]
public void TestGetMethod()
{
var service = appHost.Container.Resolve<BorrowerServices>();
BorrowerGet request = new BorrowerGet();
request.Id = 1;
var response = service.Get(request);
Assert.Equal("ormlite#servicestack.net", response.Email);
}
[Fact]
public void TestPutMethod()
{
var service = appHost.Container.Resolve<BorrowerServices>();
BorrowerUpdate request = new BorrowerUpdate();
request.Id = 5;
request.FirstName = "MyFirstName2";
request.LastName = "MyLastName2";
request.Email = "MyEmail#Example.com";
var response = service.Put(request);
Assert.True(response.FirstName == "MyFirstName2", "FirstName is noth equal");
}
}
No matter where I put the NamingStrategy statement, I get a exception from the DialectProvider property of the OrmLiteConfig class, "You must set the singleton 'OrmLiteConfig.DialectProvider' to use the OrmLiteWriteExtensions"
Where's the proper place to set this property?
Thank you,
Stephen
You can just assign it to the DialectProvider you're using, e.g:
PostgreSqlDialect.Provider.NamingStrategy = new OrmLiteNamingStrategyBase();
The OrmLiteConfig.DialectProvider is a singleton that can either be set manually:
OrmLiteConfig.DialectProvider = PostgreSqlDialect.Provider;
OrmLiteConfig.DialectProvider.NamingStrategy = new OrmLiteNamingStrategyBase();
Or implicitly with the new OrmLiteConnectionFactory() constructor, which to run, needs to resolved from the IOC:
container.Register<IDbConnectionFactory>(c => new OrmLiteConnectionFactory(...));
using (var db = container.Resolve<IDbConnectionFactory>().Open())
{
OrmLiteConfig.DialectProvider.NamingStrategy = new OrmLiteNamingStrategyBase();
}

Equivalent of JustMock's ReturnsCollection() in FakeItEasy?

With JustMock I can mock DataContext tables with lists in Linq to SQL easily like this, where an IEnumerable is taking the place of each DataContext's table through ReturnsCollection() allowing me to plug in fake data:
[TestMethod]
public void ShouldGetManagersByHireDate()
{
var context = Mock.Create<MyDataContext>();
Mock.Arrange(()=> context.Employees).ReturnsCollection(GetFakeEmployees());
Mock.Arrange(() => context.Managers).ReturnsCollection(GetFakeManagers());
var repository = new EmployeeRepository(context);
var managers = repository.GetManagersByHireDate(new DateTime(2002, 1, 1), DateTime.Now);
Assert.AreEqual(1, managers.Count());
Assert.AreEqual(1, managers.FirstOrDefault().ID);
}
private IEnumerable<Employee> GetFakeEmployees()
{
return new List<Employee> {
new Employee { ID = 1, HireDate = new DateTime(2004, 12, 1) },
new Employee { ID = 2, HireDate = new DateTime(2006, 7, 1) },
new Employee { ID = 3, HireDate = new DateTime(2009, 3, 1) }
};
}
private IEnumerable<Manager> GetFakeManagers()
{
return new List<Manager> {
new Manager { ID = 1 }
};
}
And this would be the method under test:
public IQueryable<Employee> GetManagersByHireDate(DateTime start, DateTime end)
{
return from e in context.Employees
join m in context.Managers on e.ID equals m.ID
where e.HireDate >= start && e.HireDate <= end
select e;
}
I am looking for some way of performing the same magic allowing me to use IEnumerable<T> in place of Table<T> for the purpose of testing Linq to SQL, preferably in FakeItEasy.
Linq to SQL isn't the easiest thing to test using open source tools. Hopefully, this approach may work for you.
FakeItEasy doesn't have a method exactly like JustMock's ReturnCollection that would allow you to mock out an ITable to return an IEnumerable. One option you have is to create a MockableTable similar to the one shown here. Then to populate your Table, you could have something like
private ITable<Employee> GetFakeEmployees() {
List<Employee> sampleData = /* fill it up with employees */
var employeeTable = new MockableTable<Employee>(null, sampleData.AsQuerable());
return employeeTable;
}
Also, FakeItEasy won't intercept the Employees property on the DataContext since it's a non virtual property on a concrete class. You could create a simple custom base class and have MyDataContext class derive directly from that.
public abstract class CustomDataContext : DataContext, ICustomDataContext {
}
public interface ICustomDataContext {
ITable<Employee> { get; }
}
The main point here is to leverage the interface for your mock. Then in your test method, you would have:
[TestMethod]
public void ShouldGetManagersByHireDate() {
var context = A.Fake<ICustomDataContext>();
A.CallTo(()=> context.Employees).Returns(GetFakeEmployees());
var repository = new EmployeeRepository(context);
var managers = repository.GetManagersByHireDate(new DateTime(2002, 1, 1), DateTime.Now);
Assert.AreEqual(1, managers.Count());
Assert.AreEqual(1, managers.FirstOrDefault().ID);
}
I haven't actually compiled this, but concept should be stable. Relying on the abstractions will make your code more testable and easier to mock.
Hope this helps somewhat.
The way I have done this using FakeItEasy is to add an interface to DataContext and use that as my dependency in my repos. E.g.
public interface IMyDataContext : IDisposable
{
IQueryable<Employee> Employees { get; }
// etc.
}
public partial class MyDataContext: IMyDataContext
{
IQueryable<Message> IMyDataContext.Employees
{
get { return this.Employees; }
}
// etc.
}
public class EmployeeRepository
{
public EmployeeRepository(IMyDataContext context)
{
// etc.
}
}
And in my test:
var context = A.Fake<IMyDataContext>();
A.CallTo(() => context.Employees).Returns(new[] { new Employee { Name = "John", Name = "Fred" }.AsQueryable());
var repository = new EmployeeRepository(context)
I don't think any considerations surrounding ITable are required.