InMemory DbContext在集成测试时抛出错误

时间:2017-06-14 17:35:12

标签: c# entity-framework integration-testing

错误:

  

消息:System.InvalidOperationException:实体的实例   类型'程序'无法跟踪,因为此类型的另一个实例   已经跟踪了相同的密钥。添加新实体时,   对于大多数密钥类型,如果不是,将创建唯一的临时密钥值   key被设置(即,如果为key属性分配了默认值   它的类型)。如果您明确设置新实体的键值,   确保它们不会与现有实体或临时值发生冲突   为其他新实体生成。附加现有实体时,   确保只有一个具有给定键值的实体实例   附在上下文中。

集成测试:

public class ProgramControllerIntegrationTests : MappingTestsHelper
    {
        private readonly IMapper _mapper;
        private readonly Repository<ApplicationDbContext> _repository;
        private ProgramService _programService;
        private readonly ProgramController _classUnderTest;
        private readonly ValidatorService _validatorService;
        private readonly FluentValidatorFactory _fluentValidatorFactory;
        private readonly ClaimsService _claimsService;

        public ProgramControllerIntegrationTests()
        {
            var container = new Container();
            container.Configure(c => {
                c.AddRegistry<DependencyInjectionRegistry>();
                c.For<AbstractValidator<CreateViewModel>>().Use<CreateViewModelValidator>();
            });

            _mapper = Mapper.Instance;
            _repository = new Repository<ApplicationDbContext>(GetContextWithData());
            _programService = new ProgramService(_repository, _mapper);
            _fluentValidatorFactory = new FluentValidatorFactory(container);
            _validatorService = new ValidatorService(_fluentValidatorFactory);
            _claimsService = new ClaimsService();
            _classUnderTest = new ProgramController(_programService, _claimsService, _mapper, _validatorService);
        }

        public class GetAll : ProgramControllerIntegrationTests
        {
            [Fact]
            public async void DoRequestForAllPrograms_ReturnSuccessHttpStatusAndListViewModelList()
            {
                var result = await _classUnderTest.GetAll() as ObjectResult; ;

                result.ShouldBeOfType<OkObjectResult>();
                result.StatusCode.ShouldBe(200);
                result.Value.ShouldBeOfType<List<ListViewModel>>();
            }
        }

        public class Create : ProgramControllerIntegrationTests
        {
            [Fact]
            public async void DoRequestForCreateWithCorrectData_ReturnCreatedHttpStatus()
            {
                var createviewmodel = new CreateViewModel
                {
                    Name = "Muskel Deutsche Program",
                    Length = 1,
                    TimesPerWeek = 3,
                    Type = (byte)ProgramTypeEnum.MuscleGain
                };

                var result = await _classUnderTest.Create(createviewmodel) as ObjectResult;

                result.ShouldBeOfType<OkObjectResult>();
                result.StatusCode.ShouldBe(201);
            }

            [Fact]
            public async void DoRequestForCreateWithMissingData_ReturnBadRequestHttpStatus()
            {
                var createviewmodel = new CreateViewModel
                {
                    Type = (byte)ProgramTypeEnum.MuscleGain
                };

                var result = await _classUnderTest.Create(createviewmodel) as ObjectResult;

                result.ShouldBeOfType<BadRequestObjectResult>();
                result.StatusCode.ShouldBe(400);
            }
        }

        private ApplicationDbContext GetContextWithData()
        {
            var options = new DbContextOptionsBuilder<ApplicationDbContext>()
                .UseInMemoryDatabase(Guid.NewGuid().ToString())
                .Options;

            var context = new ApplicationDbContext(options);

            var programs = new List<Context.Models.Program>
            {
                new Context.Models.Program
                {
                    CreatedBy = "d0806514-cbce-47b7-974f-c50f77d5e89c",
                    CreatedDate = new DateTime(2010, 10, 10),
                    Id = 1,
                    IsActive = true,
                    IsDeleted = false,
                    Length = 1,
                    ModifiedBy = "d0806514-cbce-47b7-974f-c50f77d5e89c",
                    ModifiedDate = new DateTime(2010, 10, 10),
                    Name = "Big Muscle",
                    TimesPerWeek = 1

                },
                //new Context.Models.Program
                //{
                //    CreatedBy = "d0806514-cbce-47b7-974f-c50f77d5e89c",
                //    CreatedDate = new DateTime(2010, 10, 10),
                //    Id = 1,
                //    IsActive = true,
                //    IsDeleted = false,
                //    Length = 1,
                //    ModifiedBy = "d0806514-cbce-47b7-974f-c50f77d5e89c",
                //    ModifiedDate = new DateTime(2010, 10, 10),
                //    Name = "Stay Fit",
                //    TimesPerWeek = 1

                //}
            };

            context.AddRangeAsync(programs);

            context.SaveChanges();

            return context;
        }
    }

问题出现在DoRequestForCreateWithCorrectData_ReturnCreatedHttpStatus方法中,我使用context将新项添加到内存DB中。当我想在同一时间向上下文中添加更多项时,会出现同样的问题,所以我认为我正在做错误的初始化。

1 个答案:

答案 0 :(得分:0)

问题是来自预制数据的Id是1和1,所以这是第一个错误,为什么两者都没有合作。另一个问题是当创建使用Id 1创建的新记录时,预制数据已经使用了Id 1,因此我只是将premade中的ID更改为98和99.

    private ApplicationDbContext GetContextWithData()
    {
        var options = new DbContextOptionsBuilder<ApplicationDbContext>()
            .UseInMemoryDatabase(Guid.NewGuid().ToString())
            .Options;

        var context = new ApplicationDbContext(options);

        var programs = new List<Context.Models.Program>
        {
            new Context.Models.Program
            {
                CreatedBy = "d0806514-cbce-47b7-974f-c50f77d5e89c",
                CreatedDate = new DateTime(2010, 10, 10),
                Id = 98,
                IsActive = true,
                IsDeleted = false,
                Length = 1,
                ModifiedBy = "d0806514-cbce-47b7-974f-c50f77d5e89c",
                ModifiedDate = new DateTime(2010, 10, 10),
                Name = "Big Muscle",
                TimesPerWeek = 1

            },
            new Context.Models.Program
            {
                CreatedBy = "d0806514-cbce-47b7-974f-c50f77d5e89c",
                CreatedDate = new DateTime(2010, 10, 10),
                Id = 99,
                IsActive = true,
                IsDeleted = false,
                Length = 1,
                ModifiedBy = "d0806514-cbce-47b7-974f-c50f77d5e89c",
                ModifiedDate = new DateTime(2010, 10, 10),
                Name = "Stay Fit",
                TimesPerWeek = 1

            }
        };

        context.AddRange(programs);

        context.SaveChanges();

        return context;
    }