Repository模式与单元测试
作者:网络转载 发布时间:[ 2016/4/6 10:17:35 ] 推荐标签:软件测试技术 单元测试
(2)在DbSettings中按需定义依赖,这里将实体类的配置也通过DbSettings注入。
1 namespace Example.Infrastructure.Repository
2 {
3 public class DbSettings
4 {
5 public DbSettings()
6 {
7 this.RowVersionNname = "Version";
8 }
9
10 public string NameOrConnectionString { get; set; }
11
12 public string RowVersionNname { get; set; }
13 public bool Debug { get; set; }
14
15 public bool UnitTest { get; set; }
16
17 public IDbConnectionFactory DbConnectionFactory { get; set; }
18
19 public List<object> EntityMaps { get; set; } = new List<object>();
20
21 public List<object> ComplexMaps { get; set; } = new List<object>();
22 }
23 }
3.定义SqlServerDbContext和VersionDbContext,解决使用开放式并发连接时,MySql等数据库无法自动生成RowVersion的问题。
(1)适用于SqlServer、SqlServeCe的SqlServerDbContext
1 namespace Example.Infrastructure.Repository
2 {
3 public class SqlServerDbContext : EfDbContext
4 {
5 private DbSettings _dbSettings;
6
7 public SqlServerDbContext(IConfiguration configuration, ILogger logger, DbSettings dbSettings)
8 : base(configuration, logger, dbSettings)
9 {
10 this._dbSettings = dbSettings;
11 }
12
13 protected override void OnModelCreating(DbModelBuilder modelBuilder)
14 {
15 base.OnModelCreating(modelBuilder);
16 modelBuilder.Properties().Where(o => o.Name == this._dbSettings.RowVersionNname).Configure(o => o.IsRowVersion());
17 base.SetInitializer<SqlServerDbContext>();
18 }
19 }
20 }
(2)适用于Myql、Sqlite等数据库的VersionDbContext。使用手动更新Version,通过GUID保证版本号。
1 namespace Example.Infrastructure.Repository
2 {
3 public class VersionDbContext : EfDbContext
4 {
5 private DbSettings _dbSettings;
6
7 public VersionDbContext(IConfiguration configuration, ILogger logger, DbSettings dbSettings)
8 : base(configuration,logger,dbSettings)
9 {
10 this._dbSettings = dbSettings;
11 }
12
13 protected override void OnModelCreating(DbModelBuilder modelBuilder)
14 {
15 base.OnModelCreating(modelBuilder);
16 modelBuilder.Properties().Where(o => o.Name == this._dbSettings.RowVersionNname)
17 .Configure(o => o.IsConcurrencyToken().HasDatabaseGeneratedOption(DatabaseGeneratedOption.None));
18 base.SetInitializer<VersionDbContext>();
19 }
20
21 public override int SaveChanges()
22 {
23 this.ChangeTracker.DetectChanges();
24 var objectContext = ((IObjectContextAdapter)this).ObjectContext;
25 foreach (ObjectStateEntry entry in objectContext.ObjectStateManager.GetObjectStateEntries(EntityState.Modified | EntityState.Added))
26 {
27 var v = entry.Entity;
28 if (v != null)
29 {
30 var property = v.GetType().GetProperty(this._dbSettings.RowVersionNname);
31 if (property != null)
32 {
33 var value = Encoding.UTF8.GetBytes(Guid.NewGuid().ToString());
34 property.SetValue(v, value);
35 }
36 }
37 }
38 return base.SaveChanges();
39 }
40 }
41 }
4.使用XUnit、Rhino.Mocks和SqlServerCe进行单元测试
这是参考nopcommerce中的做法,nopcommerce使用的NUnit需要安装NUnit扩展,XUnit只需要通过Nuget引入程序包,看看GitHub上的aspnet源码,微软也在使用XUnit。
1 namespace Example.Infrastructure.Test.Repository
2 {
3 public class CustomerPersistenceTest
4 {
5 private IRepository<T> GetRepository<T>() where T : class
6 {
7 string testDbName = "Data Source=" + (System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location)) + @"\test.sdf;Persist Security Info=False";
8 var configuration = MockRepository.GenerateMock<IConfiguration>();
9 var logger = MockRepository.GenerateMock<ILogger>();
10 var repository = new EfRepository<T>(new SqlServerDbContext(configuration,logger,new DbSettings
11 {
12 DbConnectionFactory = new SqlCeConnectionFactory("System.Data.SqlServerCe.4.0"),
13 NameOrConnectionString = testDbName,
14 Debug = true,
15 UnitTest = true,
16 EntityMaps = new List<object> { new EntityTypeConfiguration<Customer>() }
17 }));
18 return repository;
19 }
20
21 [Fact]
22 public void SaveLoadCustomerTest()
23 {
24 var repository = this.GetRepository<Customer>();
25 repository.Add(new Customer { UserName = "test" });
26 repository.Commit();
27 var customer = repository.Query.FirstOrDefault(o => o.UserName == "test");
28 Assert.NotNull(customer);
29 }
30 }
31 }
5.确保在ASP.NET中使用依赖注入时,配置DbContext的生命周期为Request范围
1 namespace Example.Web
2 {
3 public class MvcApplication : System.Web.HttpApplication
4 {
5 protected void Application_Start()
6 {
7 ObjectFactory.Init();
8 ObjectFactory.AddSingleton<IConfiguration, AppConfigAdapter>();
9 ObjectFactory.AddSingleton<ILogger, Log4netAdapter>();
10 ObjectFactory.AddSingleton<DbSettings, DbSettings>(new DbSettings { NameOrConnectionString = "SqlCeConnection", Debug = true });
11 ObjectFactory.AddScoped<IDbContext, SqlServerDbContext>();
12 ObjectFactory.AddTransient(typeof(IRepository<>), typeof(EfRepository<>));
13 ObjectFactory.Build();
14 ObjectFactory.GetInstance<ILogger>().Information(String.Format("Start at {0}",DateTime.Now));
15 AreaRegistration.RegisterAllAreas();
16 FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
17 RouteConfig.RegisterRoutes(RouteTable.Routes);
18 BundleConfig.RegisterBundles(BundleTable.Bundles);
19 }
20
21 protected void Application_EndRequest()
22 {
23 ObjectFactory.Dispose();
24 }
25 }
26 }
依赖注入这里采用的是StructureMap。HttpContextLifecycle提供了Request范围内的生命周期管理但未定义在StructureMap程序包中,需要引入StructureMap.Web程序包。使用HttpContextLifecycle时需要在Application_EndRequest调用HttpContextLifecycle.DisposeAndClearAll()方法。
本文内容不用于商业目的,如涉及知识产权问题,请权利人联系SPASVO小编(021-61079698-8054),我们将立即处理,马上删除。
相关推荐
iOS单元测试mocha、chai、sinon和istanbul实现百分之百的单元测试覆盖率关于单元测试的总结及思考编写更好的Java单元测试的7个技巧Android单元测试框架Robolectric3.0介绍(一)使用Kiwi单元测试总结单元测试如此重要,为什么你不知道Python单元测试??使用装饰器实现测试跳过和预期故障对Controller的单元测试写好单元测试的10个技巧单元测试的重要性Angular单元测试系列??Component、Directive、Pipe 以及ServiceAndroid单元测试的整理提升单元测试体验的利器--Mockito使用总结iOS UnitTest单元测试Vue的单元测试探索(二)
更新发布
功能测试和接口测试的区别
2023/3/23 14:23:39如何写好测试用例文档
2023/3/22 16:17:39常用的选择回归测试的方式有哪些?
2022/6/14 16:14:27测试流程中需要重点把关几个过程?
2021/10/18 15:37:44性能测试的七种方法
2021/9/17 15:19:29全链路压测优化思路
2021/9/14 15:42:25性能测试流程浅谈
2021/5/28 17:25:47常见的APP性能测试指标
2021/5/8 17:01:11热门文章
常见的移动App Bug??崩溃的测试用例设计如何用Jmeter做压力测试QC使用说明APP压力测试入门教程移动app测试中的主要问题jenkins+testng+ant+webdriver持续集成测试使用JMeter进行HTTP负载测试Selenium 2.0 WebDriver 使用指南