EF Core kullanan kodu test etmeTesting code that uses EF Core

Bir veritabanına erişen test kodu şunlardan birini gerektirir:Testing code that accesses a database requires either:

  • Üretimde kullanılan aynı veritabanı sisteminde sorgu ve güncelleştirme çalıştırma.Running queries and updates against the same database system used in production.
  • Veritabanı sistemini yönetmek daha kolay bir şekilde sorgu ve güncelleştirme çalıştırmak.Running queries and updates against some other easier to manage database system.
  • Herhangi bir veritabanını kullanmaktan kaçınmak için test Double değerlerini veya başka bir mekanizmayı kullanma.Using test doubles or some other mechanism to avoid using a database at all.

Bu belgede, bu seçeneklerin her birine dahil olan ve her yaklaşımla birlikte EF Core nasıl kullanılabileceği gösterilmektedir.This document outlines the trade-offs involved in each of these choices and shows how EF Core can be used with each approach.

İpucu

Burada tanıtılan kavramları gösteren kod için bkz. EF Core test örneği .See EF Core testing sample for code demonstrating the concepts introduced here.

Tüm veritabanı sağlayıcıları eşit değildirAll database providers are not equal

EF Core, temel alınan veritabanı sisteminin her yönüyle soyutlamak için tasarlanmadığı anlamak çok önemlidir.It is very important to understand that EF Core is not designed to abstract every aspect of the underlying database system. Bunun yerine, EF Core herhangi bir veritabanı sistemiyle kullanılabilecek ortak bir desenler ve kavramlar kümesidir.Instead, EF Core is a common set of patterns and concepts that can be used with any database system. EF Core veritabanı sağlayıcıları daha sonra bu ortak çerçeve üzerinde veritabanına özgü davranışı ve işlevselliği katmanlara göre.EF Core database providers then layer database-specific behavior and functionality over this common framework. Bu, her bir veritabanı sisteminin, uygun olduğunda diğer veritabanı sistemleriyle aynı zamanda en iyi şekilde ne yaptığını sağlar.This allows each database system to do what it does best while still maintaining commonality, where appropriate, with other database systems.

Temelde, bu, veritabanı sağlayıcısının geçiş EF Core davranışını değiştirecek ve davranışın herhangi bir farklılık için açıkça hesap olmadığı müddetçe uygulamanın düzgün şekilde çalışması beklenmeyeceği anlamına gelir.Fundamentally, this means that switching out the database provider will change EF Core behavior and the application can't be expected to function correctly unless it explicitly accounts for any differences in behavior. Bu, birçok durumda, ilişkisel veritabanları arasında yüksek ölçüde önem derecesine sahip olduğu için bu şekilde çalışacaktır.That being said, in many cases doing this will work because there is a high degree of commonality amongst relational databases. Bu iyi ve bozuktur.This is good and bad. Veritabanı sistemleri arasında geçiş yapmak görece kolay olabilir.Good because moving between database systems can be relatively easy. Uygulama yeni veritabanı sistemine tam olarak sınanmamışsa yanlış güvenlik özelliği verebildiğinden hatalı.Bad because it can give a false sense of security if the application is not fully tested against the new database system.

Yaklaşım 1: üretim veritabanı sistemiApproach 1: Production database system

Önceki bölümde açıklandığı gibi, üretimde çalışan işlemleri test ettiğinizden emin olmanın tek yolu aynı veritabanı sistemini kullanmaktır.As described in the previous section, the only way to be sure you are testing what runs in production is to use the same database system. Örneğin, dağıtılan uygulama SQL Azure kullanıyorsa, test da SQL Azure karşı yapılmalıdır.For example, if the deployed application uses SQL Azure, then testing should also be done against SQL Azure.

Ancak, kod üzerinde etkin olarak çalışırken her geliştiricinin SQL Azure karşı testleri çalıştırması, hem yavaş hem de pahalıdır.However, having every developer run tests against SQL Azure while actively working on the code would be both slow and expensive. Bu yaklaşım, bu yaklaşımlar boyunca ana ticareti gösterir: test verimliliğini artırmak için üretim veritabanı sisteminden ne zaman dahil olmak üzere?This illustrates the main trade-off involved throughout these approaches: when is it appropriate to deviate from the production database system so as to improve test efficiency?

Bu durumda, yanıt oldukça kolaydır: Geliştirici testi için yerel veya şirket içi SQL Server kullanın.Luckily, in this case the answer is quite easy: use local or on-premises SQL Server for developer testing. SQL Azure ve SQL Server son derece benzerdir, bu nedenle SQL Server karşı test genellikle makul bir denge olur.SQL Azure and SQL Server are extremely similar, so testing against SQL Server is usually a reasonable trade-off. Bu şekilde, üretime geçmeden önce SQL Azure kendi başına testleri çalıştırmak gene de vardır.That being said, it is still wise to run tests against SQL Azure itself before going into production.

Yerel veritabanıLocalDB

Tüm büyük veritabanı sistemleri, yerel test için bazı "Geliştirici sürümü" biçimine sahiptir.All the major database systems have some form of "Developer Edition" for local testing. SQL Server ayrıca LocalDBadlı bir özelliğe sahiptir.SQL Server also has a feature called LocalDB. LocalDB 'nin birincil avantajı, veritabanı örneğini isteğe bağlı olarak en fazla bir şekilde alır.The primary advantage of LocalDB is that it spins up the database instance on demand. Bu, testlerinizi çalıştırmayan zaman bile makinenizde bir veritabanı hizmetinin çalışmasını önler.This avoids having a database service running on your machine even when you're not running tests.

LocalDB, sorunları olmadan değil:LocalDB is not without its issues:

  • SQL Server Developer sürümünün yaptığı her şeyi desteklemez.It doesn't support everything that SQL Server Developer Edition does.
  • Linux üzerinde kullanılamaz.It isn't available on Linux.
  • Hizmet geçersiz olduğu için ilk Test çalıştırmasında gecikme oluşmasına neden olabilir.It can cause lag on first test run as the service is spun up.

Kişisel olarak, geliştirme makinmda çalışan bir veritabanı hizmetine sahip bir sorun buldum ve genellikle bunun yerine geliştirici sürümü kullanmanızı öneririz.Personally, I've never found it a problem having a database service running on my dev machine and I would generally recommend using Developer Edition instead. Ancak, özellikle daha az güçlü geliştirme makinelerinde, LocalDB bazı kişiler için uygun olabilir.However, LocalDB may be appropriate for some people, especially on less powerful dev machines.

Bir Docker kapsayıcısında (veya benzer) SQL Server (veya başka bir veritabanı sistemi) çalıştırmak , veritabanı sistemini doğrudan geliştirme makinenizde çalıştırmayı önlemek için başka bir yoldur.Running SQL Server (or any other database system) in a Docker container (or similar) is another way to avoid running the database system directly on your development machine.

Yaklaşım 2: SQLiteApproach 2: SQLite

EF Core, birincil olarak yerel bir SQL Server örneğine karşı çalıştırarak SQL Server sağlayıcıyı sınar.EF Core tests the SQL Server provider primarily by running it against a local SQL Server instance. Bu sınamalar, hızlı bir makinede birkaç dakikada on binlerce sorgu çalıştırır.These tests run tens of thousands of queries in a couple of minutes on a fast machine. Bu, gerçek veritabanı sisteminin kullanımı bir performanslı çözüm olabilir.This illustrates that using the real database system can be a performant solution. Daha hafif bir veritabanı kullanmanın, testleri hızlı bir şekilde çalıştırmanın tek yolu olan bir efsaneyi bu değildir.It is a myth that using some lighter-weight database is the only way to run tests quickly.

Bu, ne olursa olsun, testleri üretim veritabanı sisteminize yakın bir şeye karşı çalıştıramıyorum?That being said, what if for whatever reason you can't run tests against something close to your production database system? Bir sonraki en iyi seçenek, benzer işlevlerle bir şeyi kullanmaktır.The next best choice is to use something with similar functionality. Bu genellikle, SQLite 'un açık seçim olduğu başka bir ilişkisel veritabanı anlamına gelir.This usually means another relational database, for which SQLite is the obvious choice.

SQLite iyi bir seçimdir çünkü:SQLite is a good choice because:

  • Uygulamanızla birlikte işlem içinde çalışır ve bu nedenle düşük ek yük vardır.It runs in-process with your application and so has low overhead.
  • Veritabanları için basit, otomatik olarak oluşturulan dosyalar kullanır, bu nedenle veritabanı yönetimine gerek yoktur.It uses simple, automatically created files for databases, and so doesn't require database management.
  • Dosya oluşturulmasını engelleyen bir bellek içi modu vardır.It has an in-memory mode that avoids even the file creation.

Bununla birlikte şunları unutmayın:However, remember that:

  • SQLite inevilebilirlik, üretim veritabanı sisteminizin yaptığı her şeyi desteklemez.SQLite inevitability doesn't support everything that your production database system does.
  • SQLite, bazı sorgular için üretim veritabanı sisteminizden farklı davranır.SQLite will behave differently than your production database system for some queries.

Bu nedenle, bazı testler için SQLite kullanırsanız, gerçek veritabanı sisteminize göre de test ettiğinizden emin olun.So if you do use SQLite for some testing, make sure to also test against your real database system.

EF Core belirli bir kılavuz için bkz. SQLite Ile test etme .See Testing with SQLite for EF Core specific guidance.

Yaklaşım 3: bellek içi EF Core veritabanıApproach 3: The EF Core in-memory database

EF Core, EF Core iç testi için kullandığımız bellek içi veritabanı ile birlikte gelir.EF Core comes with an in-memory database that we use for internal testing of EF Core itself. Bu veritabanı genel olarak EF Core kullanan uygulamaları test etmek için uygun değildir.This database is in general not suitable for testing applications that use EF Core. Özellikle:Specifically:

  • İlişkisel bir veritabanı değil.It is not a relational database.
  • İşlemleri desteklemez.It doesn't support transactions.
  • Ham SQL sorguları çalıştırılamaz.It cannot run raw SQL queries.
  • Performans için en iyi duruma getirilmemiştir.It is not optimized for performance.

Bu, özellikle veritabanının teste ilgisiz olduğu durumlarda kullandığımızda, EF Core iç yapıları test edilirken bu çok önemli değildir.None of this is very important when testing EF Core internals because we use it specifically where the database is irrelevant to the test. Diğer taraftan, EF Core kullanan bir uygulama test edilirken bu şeyler çok önemli olmaya eğilimlidir.On the other hand, these things tend to be very important when testing an application that uses EF Core.

Birim testiUnit testing

Bir veritabanından bazı verileri kullanması gerekebilecek, ancak veritabanı etkileşimlerini doğal olarak test etmediğinden, bir iş mantığı parçasını test etmeyi düşünün.Consider testing a piece of business logic that might need to use some data from a database, but is not inherently testing the database interactions. Bir seçenek, bir model veya sahte gibi bir Test Double 'ı kullanmaktır.One option is to use a test double such as a mock or fake.

EF Core iç testi için test Double değerleri kullanıyoruz.We use test doubles for internal testing of EF Core. Ancak, DbContext veya IQueryable 'yi hiçbir şekilde denemedik.However, we never try to mock DbContext or IQueryable. Bunu yapmak zor, kısabera ve Fragile.Doing so is difficult, cumbersome, and fragile. Bunu yapmayın.Don't do it.

Bunun yerine, DbContext kullanan bir şeyi birim testi yaparken EF bellek içi veritabanını kullanırız.Instead we use the EF in-memory database when unit testing something that uses DbContext. Bu durumda, bellek içi EF veritabanını kullanmak uygun olduğundan, test veritabanı davranışına bağımlı değildir.In this case using the EF in-memory database is appropriate because the test is not dependent on database behavior. Yalnızca gerçek veritabanı sorgularını veya güncelleştirmelerini test etmek için bunu yapmayın.Just don't do this to test actual database queries or updates.

EF Core test örneği , sınama ve SQL Server ve SQLite, bellek içi veritabanı kullanan testleri gösterir.The EF Core testing sample demonstrates tests using the EF in-memory database, as well as SQL Server and SQLite.