0

iam starting writing test for my data access layer and iam looking for best practice.

Now iam testing with a real db wich is auto generated from EF every times it find some differences in my model (defined with code-first fluent mapping) but doing this with many developers is difficult since every ones have different object developed.

1) So there are way to use some in memory database?
a)If don't use a connection string in my test project seen that all works fine but where is this db created?
b) EF create it one time for every test or only when first test start? Can i create it in explicit way?
c) how can this db be deleted?

2) What's i have to test?
a) in my past application i made many error in mapping object property to db column so this seem a thing to test: maybe i can create an object, save it to db, read it from db and test that all property read is equal to what i wrote
b) i think i will use repository pattern, so every object will have own repository with CRUD operations, i have to test this CRUD or it means iam testing EntityFramework itself?
c) after some times i will have many list method in my repository so i will have to insert some fake data in my db and try to query against them to test my method?
d) other things to test?

Thanks

EDIT: i tiny example:

if i map my class:

MyClass{
    public int MyClassIdField
    public string MyClassDescriptionField
}

to table [T01_Table1] with field
int_T01_Table1Id
nvc_T01_Table1Description

i want to define a test for this mapping both for testing correctness and from the point of view of test driven development

Other question: when iam testing inserting operation in db i can use my domain layer object directly or i have to mock them?
without mock i have to use the object constructor that could not work

EDIT 2: in meantime iam using a local db to go on and find other issue: i create a class in this way:

var fixture = new Fixture();
MyClass c = New MyClass();
c.id = fixture.Create<int>();
c.endDate= fixture.Create<DateTime?>();
context.MyClass.Add(c);
context.SaveChanges();

context.Dispose(); // TO force EF query on DB
context= new MyContext();

MyClass actual = context.MyClass.Find(c.Id);

//Assert
actual.DataFine.Value.Should().Be(target.DataFine.Value);

but test fail with this error:
Failure: Expected date and time to be <2014-02-22 16:14:53.901>, but found <2014-02-22 16:14:53.900>.

if don't dispose context the test in successful. how can the data change?

gt.guybrush
  • 1,320
  • 3
  • 19
  • 48

1 Answers1

1

A good rule of thumb when unit testing is not to test code outside of your scope. This would mean not testing the database itself, but mock the database with a mocking library like Moq for example.

Edit: As for integration testing. If you want to test the database itself, you need to use a real database, otherwise you would not test the database engine, but a mocked one, which would miss the target of your test. To use an mdf-file, as you mention, is an approach that would work.

cederlof
  • 7,206
  • 4
  • 45
  • 62
  • but my scope is database itself: how can i test if table are created correctly with a mock db? – gt.guybrush Apr 29 '14 at 06:49
  • 2
    Well in that case you can not use a mock db. It the keyword you are looking for is "integration test" and not "unit test". See for example: http://tech.trailmax.info/2014/03/how-we-do-database-integration-tests-with-entity-framework-migrations/ – cederlof Apr 29 '14 at 08:05
  • correct, i edit the title. Interesting article but don't find the way to have a db for each developer. I have created a mdf file in my test project but don't know connection string to use – gt.guybrush Apr 29 '14 at 08:28
  • and if possible i will prefer to use an in-memory db. iam exploring "effort" to see if can do the work – gt.guybrush Apr 29 '14 at 08:31
  • ok, i find correct string for mdf connection and testing works. however I'd rather find a solution in memory – gt.guybrush Apr 29 '14 at 08:50
  • any way for using an in-memory db? and how i can reset my db after every test method? – gt.guybrush Apr 29 '14 at 12:51
  • I don't know for in-memory db. Refer to this for unit testing with DropCreateDatabaseAlways: http://stackoverflow.com/questions/13732532/recreate-and-reseed-localdb-before-each-unit-test – cederlof Apr 29 '14 at 13:06
  • they recreate db for each test, can be very time consuming. i try to use transaction for each test but during trans i cannot query db to find real data writed – gt.guybrush Apr 29 '14 at 13:28
  • I have not heard of a testing solution like that - if you need the database to be reset after each test, to recreate it would be the solution I would go for. Unit testing the database at all gives you a lot of time consuming jobs - something I would not do for small queries, only do it for a small number of larger integration tests, and recreate the database for each test run. – cederlof Apr 29 '14 at 13:31
  • @gt.guybrush Please post a new question on StackOverflow with the new problem, and keep the original question here. You will have a better chance of getting an answer that way, and the questions on SO will be cleaner. If my reply is considered an answer to your original question, you may mark it as accepted. – cederlof Apr 30 '14 at 08:54
  • iam still looking for an in-memory version but due to too many problem i switch to nhibernate and till now seems a winning switch – gt.guybrush May 02 '14 at 14:18
  • 1
    @gt.guybrush If you use sql server, there was no in-memory option until SQL Server 2014 was released. With SQL Server 2014 you can have in-memory database. However, I have not tried that, only read articles about this feature. – trailmax Jun 13 '14 at 10:56