我在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);
}
}
答案 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);
}