多语句事务中不允许CREATE DATABASE语句。在TFS自动构建上

时间:2016-01-23 22:29:53

标签: c# asp.net-mvc entity-framework unit-testing tfs

我在TFS上创建了一个CI,我在测试自动化上得到了这个错误

Test method xx.xx.Tests.Controllers.TipoDeCanalesControllerTest.DeleteTipoDeCanal threw exception: 
System.Data.SqlClient.SqlException: CREATE DATABASE statement not allowed within multi-statement transaction.
    at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
   at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
   at System.Data.Sq

该项目是一个asp.net mvc应用程序,单元测试正在测试webapi控制器,我也首先使用实体​​框架代码,这应该创建一个数据库。

http://screencast.com/t/fY7sZXeCy

,测试代码如下:

 public class TipoDeCanalesControllerTest
    {
        [TestMethod]
        public void PostTipoDeCanal()
        {
            TipoDeCanalesController controller = NewController();

            // Act
            TipoDeCanal tipoDeCanal = new TipoDeCanal() { Descripcion = "Unit Test Des", Nombre = "Unit Test" };
            var response = new HttpResponseMessage();
            using (System.Transactions.TransactionScope ts = new System.Transactions.TransactionScope())
            {
                response = controller.PostTipoDeCanal(tipoDeCanal);
                ts.Dispose();
            }

            // Assert
            Assert.AreEqual(System.Net.HttpStatusCode.Created,
               response.StatusCode);
        }

        [TestMethod]
        public void PutTipoDeCanal()
        {
            TipoDeCanalesController controller = NewController();

            // Act
            TipoDeCanal tipoDeCanal = new TipoDeCanal() { Descripcion = "Unit Test Description", Nombre = "Unit Test" };
            var response = new HttpResponseMessage();
            using (System.Transactions.TransactionScope ts = new System.Transactions.TransactionScope())
            {
                controller.PostTipoDeCanal(tipoDeCanal);
                tipoDeCanal.Nombre = "Edit Unit Test";
                tipoDeCanal.Descripcion = "Unit Test Edit Description";
                response = controller.PutTipoDeCanal(tipoDeCanal.ID, tipoDeCanal);
                ts.Dispose();
            }

            // Assert
            Assert.AreEqual(System.Net.HttpStatusCode.OK,
               response.StatusCode);
        }

        [TestMethod]
        public void DeleteTipoDeCanal()
        {
            TipoDeCanalesController controller = NewController();

            // Act
            TipoDeCanal tipoDeCanal = new TipoDeCanal() { Descripcion = "Unit Test Des", Nombre = "Unit Test" };
            var response = new HttpResponseMessage();
            using (System.Transactions.TransactionScope ts = new System.Transactions.TransactionScope())
            {
                controller.PostTipoDeCanal(tipoDeCanal);
                response = controller.DeleteTipoDeCanal(tipoDeCanal.ID);
                ts.Dispose();
            }

            // Assert
            Assert.AreEqual(System.Net.HttpStatusCode.OK,
               response.StatusCode);
        }

        [TestMethod]
        public void GetTipoDeCanal()
        {
            TipoDeCanalesController controller = NewController();

            // Act
            var tipoCanal = new TipoDeCanal();
            var tipoDeCanal = new TipoDeCanal() { Descripcion = "Unit Test Des", Nombre = "Unit Test" };
            var response = new HttpResponseMessage();
            using (System.Transactions.TransactionScope ts = new System.Transactions.TransactionScope())
            {
                controller.PostTipoDeCanal(tipoDeCanal);
                tipoCanal = controller.GetTipoDeCanal(tipoDeCanal.ID);
                ts.Dispose();
            }
            Assert.IsNotNull(tipoCanal);
        }

        [TestMethod]
        public void GetTiposDeCanal()
        {
            TipoDeCanalesController controller = NewController();

            // Act
            var request = new DataSourceRequest();
            var result = new DataSourceResult();
            var response = new HttpResponseMessage();
            var tipoDeCanal = new TipoDeCanal() { Descripcion = "Unit Test Des", Nombre = "Unit Test" };
            using (System.Transactions.TransactionScope ts = new System.Transactions.TransactionScope())
            {
                controller.PostTipoDeCanal(tipoDeCanal);
                result = controller.GetTiposDeCanal(request);
                ts.Dispose();
            }
            Assert.IsTrue(result.Total >=1);
        }

        private static TipoDeCanalesController NewController()
        {
            TipoDeCanalesController controller = new TipoDeCanalesController();

            controller.Request = new HttpRequestMessage
            {
                RequestUri = new Uri("http://localhost/api/TipoDeCanales")
            };
            controller.Configuration = new HttpConfiguration();
            controller.Configuration.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{id}",
                defaults: new { id = RouteParameter.Optional });

            controller.RequestContext.RouteData = new HttpRouteData(
                route: new HttpRoute(),
                values: new HttpRouteValueDictionary { { "TipoDeCanalesController", "TipoDeCanal" } });
            return controller;
        }

和web api控制器

public class TipoDeCanalesController : GenericApiController
    {
        private UnitOfWork unitOfWork = new UnitOfWork();

        // GET api/TipoDeCanal/5
        public TipoDeCanal GetTipoDeCanal(int id)
        {
            TipoDeCanal tipoDeCanal = unitOfWork.TipoDeCanalRepository.GetByID(id);
            if (tipoDeCanal == null)
            {
                throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.NotFound));
            }

            return tipoDeCanal;
        }

        // GET api/TiposDeCanal
        public DataSourceResult GetTiposDeCanal([System.Web.Http.ModelBinding.ModelBinder(typeof(WebApiDataSourceRequestModelBinder))]DataSourceRequest request)
        {
            TipoDeCanal[] tiposDeCanal = unitOfWork.TipoDeCanalRepository.Get().ToArray();
            DataSourceResult result = tiposDeCanal.ToDataSourceResult(request);
            return result;
        }

        // PUT api/TipoDeCanal/            edit
        public HttpResponseMessage PutTipoDeCanal(int id, TipoDeCanal tipoDeCanal)
        {
            if (!ModelState.IsValid)
            {
                return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState);
            }

            if (id != tipoDeCanal.ID)
            {
                return Request.CreateResponse(HttpStatusCode.BadRequest);
            }

            try
            {
                unitOfWork.TipoDeCanalRepository.Update(tipoDeCanal);
                unitOfWork.Save();
            }
            catch (DbUpdateConcurrencyException ex)
            {
                return Request.CreateErrorResponse(HttpStatusCode.NotFound, ex);
            }

            return Request.CreateResponse(HttpStatusCode.OK);
        }

        // POST api/TiposDeCanal   add
        public HttpResponseMessage PostTipoDeCanal(TipoDeCanal tipoDeCanal)
        {
            if (ModelState.IsValid)
            {
                unitOfWork.TipoDeCanalRepository.Insert(tipoDeCanal);
                unitOfWork.Save();

                DataSourceResult result = new DataSourceResult
                {
                    Data = new[] { tipoDeCanal },
                    Total = 1
                };
                HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.Created, result);
                response.Headers.Location = new Uri(Url.Link("DefaultApi", new {Controller="TipoDeCanalesController", id = tipoDeCanal.ID}));
                return response;
            }
            else
            {
                return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState);
            }
        }

        // DELETE api/TipoDeCanal/5
        public HttpResponseMessage DeleteTipoDeCanal(int id)
            {
            TipoDeCanal tipoDeCanal= unitOfWork.TipoDeCanalRepository.GetByID(id);
            if (tipoDeCanal == null)
            {
                return Request.CreateResponse(HttpStatusCode.NotFound);
            }

            unitOfWork.TipoDeCanalRepository.Delete(tipoDeCanal.ID);           

            try
            {
                unitOfWork.Save();
            }
            catch (DbUpdateConcurrencyException ex)
            {
                return Request.CreateErrorResponse(HttpStatusCode.NotFound, ex);
            }

            return Request.CreateResponse(HttpStatusCode.OK, tipoDeCanal);
        }   

        protected override void Dispose(bool disposing)
        {
            unitOfWork.Dispose();
            base.Dispose(disposing);
        }
    }

1 个答案:

答案 0 :(得分:0)

我能够像这样解决它:

  public class TestBase
    {
        private TransactionScope _transactionScope;
        private GenericRepository<TipoDeCanal> _repository;
        private ComisionesContext _dataSource;

        private static bool _isInitialized = false;
        public TestBase()
        {
            if (!_isInitialized)
            {
                TestClassInitialize();
                _isInitialized = true;
            }
        }

        public void TestClassInitialize()
        {
            _repository = new GenericRepository<TipoDeCanal>(ConfigurationManager.ConnectionStrings["ComisionesContext"].ConnectionString);
            _dataSource = new ComisionesContext(ConfigurationManager.ConnectionStrings["ComisionesContext"].ConnectionString);
            _dataSource.Database.Delete();
            _dataSource.Database.CreateIfNotExists();
            _transactionScope = new TransactionScope();
        }
    }

然后进行单元测试

 public class TipoDeCanalesControllerTest : TestBase
    {


        [TestMethod]
        public void PostTipoDeCanal()
        {
            TipoDeCanalesController controller = NewController();

            // Act
            TipoDeCanal tipoDeCanal = new TipoDeCanal() { Descripcion = "Unit Test Des", Nombre = "Unit Test" };
            var response = new HttpResponseMessage();
            using (System.Transactions.TransactionScope ts = new System.Transactions.TransactionScope(TransactionScopeOption.RequiresNew))
            {
                response = controller.PostTipoDeCanal(tipoDeCanal);
                ts.Dispose();
            }

            // Assert
            Assert.AreEqual(System.Net.HttpStatusCode.Created,
               response.StatusCode);
        }