I'm creating some test using ms test for an already written routine that use entity framework, and I would like to use the [DataSource] attribute to generate a test routine for a set of data in the database.
My problem is that I can just select a Table and load the single fields in the test, but I would like to fetch directly a set ob ef entities and process directly in the test routine, in a way much more similar to the way the code to test is wrote.
Exist some kind of [EFDatasource] that let me express a Ef query as datasource and use the entity in the test?
thanks,
luca
You should just use a context instance (or service/repository, what have you) in your unit test method and get the entities from it. You can supply the connection string in a config file in the unit test project. This way the test methods will be totally relieved from any connection worries. They just instantiate objects and work with them.
Some will probably comment that this is not unit testing but integration testing and that you should mock the EF context, but that is virtually impossible. Testing EF should be done with... EF.
Related
Using xUnit and the TestServer from Microsoft.AspNet.TestHost, how can I wrap each test in a database transaction that can be rolled back after the test?
Here's how I create the TestServer:
TestServer = new TestServer(TestServer.CreateBuilder()
.UseStartup<Startup>());
The Startup that's referenced there is the Startup from the web app project. In the ConfigureServices method in that Startup class I add EF like this:
services.AddEntityFramework()
.AddSqlServer()
.AddDbContext<TrailsDbContext>(options => options.UseSqlServer(Configuration["Data:DefaultConnection:ConnectionString"]));
I could pull the DbContext back of services and store a static reference on the Startup class, but that seems pretty hacky. Is there any way I can instantiate the DbContext where I create the TestServer and somehow have the web app use that instead of the one in the Startup class?
Edit: I have tried instantiating another instance of the DbContext where I create the TestServer and using that context to delete and recreate the database before each test, but that adds about 10 seconds to each test's run time.
Some advice: the simplest approach would be to destroy the test database at the end and recreate for each test run. This ensures no lingering test-to-test contamination.
But since you asked how, this can be done by extending Xunit. Xunit allows you to define custom test cases and test runners. A complete answer is hard to include in a SO answer. The simplest solution uses ambient transactions. (Danger! Ambient transactions can be tricky.) Xunit has a sample for a custom BeforeAfterTestAttribute that rolls back a transaction. https://github.com/xunit/samples.xunit/tree/master/AutoRollbackExample. To use ambient transactions, turn off the default EF setting that throws if ambient transactions are present.(optionsBuilder.UseSqlServer().SuppressAmbientTransactionWarning()).
A more complicated, but better solution is to override XunitTestCaseRunner and inject a transaction into each test case, ensuring to rollback at the conclusion of each test.
Also, EF docs provides a sample of using the InMemory provider to test. You may find this useful.
"Testing In Memory : EF Core Docs"
I have am about to retro-code a suite of unit tests for a new MVC4 app. Because nearly all my code in the EF data project is copied straight from code generated by the VS2012 EF Reverse Engineering tool, I have decided to skip unit tests in this part of the application, unless I can somehow automatically generate them. I have no business logic at here and I would like to first concentrate my efforts on ensuring better QA on the business side. But, I would like to know how one goes about first TDD, and second, just unit testing in general here.
Let's assume I don't have to or want to mock the database yet. I have often been quite happy unit testing against a test DB copy before, but with more conventional, home rolled ORM.
So, do I start with a test that instantiates my drived DbContext, then derive a DbContext until that test passes. Then, test for instantiating an entity, and create an entity, going on to test for a DbSet of those entities, which test will also include checking if the table is created. All is still good and well, if not bloody laborious, but my head asplode as soon as I start thinking of even a hint of testing my fluent mapping classes for all my entities. What now?
Testing against database is not unit testing - it is integration testing and integration testing usually doesn't follow the granularity of unit testing. Why it is not unit testing? Because unit testing tests single self contained unit - all external dependencies are faked. When your test spans both your unit code and database it test dependency as well = it is integration test.
All EF dependent code should be tested with integration testing. It doesn't make sense to unit test Microsoft's code. For example your question about mapping. Correct unit test for mapping does something like:
Preparation: Prepare compiled model with your entity mapping configuration
Execution: Create DbContext from compiled model and get metadata workspace from the context
Validation: Assert that metadata context contains your mapped entity
Now you can repeat similar test for every property you want to map in that entity.
That is obviously framework code which should already work - these tests should be done by people developing the framework.
In your case simple make integration test against local database which will try to load, save, update and delete entity and assert expectations you have on these operations. If anything in mapping is wrong at least one of these tests will fail.
I wish to unit test my business logic is loading the correct data by loading an entity via the business logic and comparing it to an entity loaded directly from the dbcontext.
Assert.AreEqual fails I'm guessing because the entities are loaded as tracked.
I thought that I could possibly use AsNoTracking(), but it didn't work.
Is there a way of "unwrapping" the entity from entity framework to a POCO?
I've read about disabling proxycreation, but is this the only option?
I'm hoping there is something similar (although I realise a completely different concept), to ko.utils.unwrapObservable() in the knockout javascript library.
It is strange integration test (it is not unit test at all because it uses database) - it should be enough to simply define static expectation instead of loading it again from the database. Dynamic tests are more error prone and can hide issues.
To make it work you must override Equal to compare data not references. Disabling proxy creation will not work because you will still have different reference from your business logic and different reference from tested context (unless you share the context but in such case the test will be even more strange).
Can it be done without using TypeMock Islolator? I've found a few suggestions online such as passing in a metadata only connection string, however nothing I've come across besides TypeMock seems to truly allow for a mock ObjectContext that can be injected into services for unit testing. Do I plunk down the $$ for TypeMock, or are there alternatives? Has nobody managed to create anything comparable to TypeMock that is open source?
I'm unit testing EF4 easily without mocking. What I did was create a repository interface using the code from http://elegantcode.com/2009/12/15/entity-framework-ef4-generic-repository-and-unit-of-work-prototype/ as a basis I then created an InMemoryRepository<T> class that used the IRepository interface. I then replaced the IObjectSet<T> with a List<T> inside of the class and changed the retrieval methods accordingly.
Thus if you need to do unit testing, pass in the InMemoryRepository rather than the DataRepository.
Put your Linq2Entity query behind an interface, unit test it in isolation against a real database.
Write tests for your business logic with mocks for your query interfaces. Don't let Linq bleed into your business logic!
Don't use the RepositoryPattern!
Wrap the ObjectContext in a proxy class. Then inject that into your classes.
I don't think the repository pattern is the only answer to the question (it avoids the problem, sure)
I liked this answer - I think more appropriate for introducing tests to an existing codebase Creating Interface for ObjectContext
Is it possible to mock an EF model so that I can test code which uses the model classes without getting rid of LINQ to Entities code strewn throughout my project? Or will it be necessary to set up a test database for the model to hit instead?
You could wrap your LINQ code in Data Access Objects. The DAOs would have separate interface and implementation code. Your test code would mock the DAOs.
If you don't want to do that, you'll need a test DB.