Visual Studio Online Unit Test and localDb

I have a solution built on Visual Studio Online. All unit tests in this solution require a database, I tried to force the assembly to use the test allocated by localdb (adding a light test file to the test project and using the localdb binding string), but it does not work with this error (everything works fine on my desktop) :

System.Data.SqlClient.SqlException: Connection timed out. The waiting period has expired while trying to use an authorization confirmation confirmation before entering the system. This may be due to the fact that the handshake before entering the system failed or the server was unable to respond on time. The duration spent trying to connect to this server was - [Pre-Login] initialization = 29460; acknowledgment = 161; ---> System.ComponentModel.Win32Exception: timeout suspended.

EDIT

Connection string

<add name="TestDb" connectionString="Data Source=(LocalDb)\v11.0;Initial Catalog=AeroBase;Integrated Security=true;AttachDBFilename=|DataDirectory|\App_Data\AeroBase.mdf" providerName="System.Data.SqlClient" /> 

I first use the EF6 code, the repository, and the work template block to access it. Here is the DbContext:

 public class AeroDataContext : DbContext, IDbContext { private Guid DataContextId; private string _name; public string Name { get { return _name; } } public AeroDataContext(string cnxStringName, string cnxString) : base(cnxString) { this.Database.Log = delegate(String name) { // Debug.WriteLine(name); }; _name = cnxStringName; this.Configuration.LazyLoadingEnabled = false; DataContextId = Guid.NewGuid(); Debug.WriteLine("AeroDbCreation Id = " + DataContextId.ToString()); } } 

DbContext is started using unitOfWorkScope:

  public class UnitOfWorkFactory : IUnitOfWorkFactory { private string _cnxStringName; private string _cnxString; public UnitOfWorkFactory(string cnxStringName, string cnxString) { _cnxString = cnxString; _cnxStringName = cnxStringName; } public IUnitOfWorkScope GetUnitOfWorkScope(bool disposeAtEndOfContext = true) { return new UnitOfWorkScope(new AeroDataContext(_cnxStringName, _cnxString), disposeAtEndOfContext); } } 

which allow me to do such things in the test (and in the application)

  [TestMethod] public void DB_Get_LFFE_Airport_By_ICAOInclude_SubType() { //structuremap container built in the TestInitilized method IUnitOfWorkFactory _uowf = container.GetInstance<IUnitOfWorkFactory>(); using (IUnitOfWorkScope uows = _uowf.GetUnitOfWorkScope(true)) { IAirportRepository repo = uows.GetRepository<IAirportRepository>(); Airport ar = repo.SearchByICAO("LFFE").FirstOrDefault(); AirportValidator.LFFE(ar); } } 

Is it possible that this is a scenario? is there any other way to do this?

thanks

+6
source share
1 answer

Most likely, this is due to the fact that LocalDb is not initialized on the VSO build server, which is twisted to start the build.

According to https://github.com/ritterim/automation-sql , LocalDb can be installed but not initialized.

LocalDB installed but cannot connect

You may have installed LocalDB, but you never initialized the instance on your machine. Run this command using the command line.

LocalDB SQL EXPRESS 2014

"C: \ Program Files \ Microsoft SQL Server \ 120 \ Tools \ Binn \ SqlLocalDB.exe" create "v12.0" 12.0 -s LocalDB SQL Express 2012

"C: \ Program Files \ Microsoft SQL Server \ 110 \ Tools \ Binn \ SqlLocalDB.exe" create "v11.0" 11.0 -s Verify that the command worked using SQL Server Management Studio to connect to the instance.

My decision:

Each time VSO starts the build, it creates a new virtual machine from the template to start the build. In my case, I would like to create a small LocalDb database dynamically to run unit tests against.

I am using the RimDev.Automation.Sql nuget package ( http://www.nuget.org/packages/RimDev.Automation.Sql/ ) so that my tests can programmatically create a database.

I also wanted to integrate with Unity and Entity Framework 6 so that it would maximize my access to the database in production. To do this, I created a class on which all my tests are inherited. One thing I wanted was to use the same database for all my tests, so I created a static LocalDb creation.

In addition, initialization runs a set of scripts in the Resources folder to pre-populate the database with stock data, if you wish. You need to make sure that sql scripts are marked for copying to the output folder (see Properties) so that the files are in the correct path when the unit test is executed.

If you want to create a new database for each test class or even for each test, this can be easily changed.

 using System; using System.Data.Entity; using System.IO; using Microsoft.Practices.Unity; using Playground.Model; using RimDev.Automation.Sql; namespace Playground.UnitTests { public abstract class TestBaseClass { // For now, these are static. We may want to change them at some point // to be per class so we create separate databases for each class run, but // for now, let not do that for speed sake. private static readonly IUnityContainer _container = new UnityContainer(); private static bool _isRegistered = false; private static readonly object _syncRoot = new object(); private static LocalDb LocalDb = new LocalDb(databaseName: "PlaygroundTestDb", databasePrefix: "pg", version: "v12.0"); private static bool _isInitialized = false; protected TestBaseClass() { RegisterComponents(_container); InitializeData(); _container.BuildUp(GetType(), this); } private void InitializeData() { lock (_syncRoot) { if (!_isInitialized) { var dbContext = _container.Resolve<PlaygroundEntities>(); Database.SetInitializer( new MigrateDatabaseToLatestVersion<PlaygroundEntities, Playground.Model.Migrations.Configuration>()); // Make sure database exists. dbContext.Database.Initialize(true); foreach ( var f in Directory.GetFiles(Path.Combine(Environment.CurrentDirectory, "Resources"), "*.sql")) { dbContext.Database.ExecuteSqlCommand(File.ReadAllText(f)); } } _isInitialized = true; } } private void RegisterComponents(IUnityContainer container) { lock (_syncRoot) { if (!_isRegistered) { // WARNING! Most methods in the unity container are not thread safe. See http://unity.codeplex.com/discussions/27496 // We may need to expose protected methods to register certain types. For now, assume all of the // tests use the same injected objects. If a test REALLY needs to a different dependency, the test can // manually create it as well. container.RegisterType<PlaygroundEntities, PlaygroundEntitiesTest>(new TransientLifetimeManager(), new InjectionConstructor(new object[] {LocalDb.ConnectionString})); } _isRegistered = true; } } } } 

Here is a test example:

 using System.Linq; using Microsoft.Practices.Unity; using Microsoft.VisualStudio.TestTools.UnitTesting; using Playground.Model; namespace Playground.UnitTests { [TestClass] public class UnitTest1 : TestBaseClass { [Dependency] public PlaygroundEntities Db { get; set; } private static bool _initialized = false; [TestInitialize] public void TestInitialize() { if (!_initialized) { Db.Playgrounds.Add(new Playground.Model.Playground() {Name = "Dave playground", Location = "SomeTown"}); Db.SaveChanges(); _initialized = true; } } [TestMethod] public void TestMethod1() { var p = Db.Playgrounds.FirstOrDefault(pg => pg.Name == "Dave playground"); Assert.IsNotNull(p); } [TestMethod] public void TestMethod2() { var p = Db.Playgrounds.FirstOrDefault(pg => pg.Location == "SomeTown"); Assert.IsNotNull(p); } } } 

Finally, in my test project, I have a test object object.

 using Playground.Model; namespace Playground.UnitTests { public class PlaygroundEntitiesTest : PlaygroundEntities { private PlaygroundEntitiesTest() { } public PlaygroundEntitiesTest(string connectionString) : base(connectionString) { } } } 

In my model project, I have an entity and my context.

Playground.cs

 using System; namespace Playground.Model { public class Playground { public Guid Id { get; set; } public string Name { get; set; } public string Location { get; set; } } } 

PlaygroundEntities.cs

 using System.Data.Entity; namespace Playground.Model { public class PlaygroundEntities : DbContext { public PlaygroundEntities() : base("PlaygroundConnectionString") { } public PlaygroundEntities(string connectionString) : base(connectionString) { } public virtual DbSet<Playground> Playgrounds { get; set; } } } 

Finally, I installed the post-build step in the unit test project to execute the command to initialize LocalDb as follows:

Project Settings for post-build Full team

"C: \ Program Files \ Microsoft SQL Server \ 120 \ Tools \ Binn \ SqlLocalDB.exe" create "v12.0" 12.0 -s

Then it was as simple as clicking on Visual Studio Online and starting my build.

enter image description here

+9
source

All Articles