title: Mocking EF6 with validation that occurs on SaveChanges
body: <p>I found a decent article to get me started on unit testing my Entity Framework-based application using Moq: <a href="https://msdn.microsoft.com/en-us/data/dn314429.aspx" rel="nofollow">https://msdn.microsoft.com/en-us/data/dn314429.aspx</a></p>
  
  <p>This issue I'm having is that the <code>SaveChanges</code> method of the Mock does not appear to trigger the <code>ValidateEntity</code> method like it normally would. None of the validation settings I configured in the <code>EntityTypeConfiguration</code> are being thrown as a <code>DbEntityValidationException</code>.</p>
  
  <p>For example, my <code>AddRoles_Fails_For_Empty_Name</code> tests to make sure that the service cannot add a role with an empty name. Either the <code>IsRequired()</code> configuration is not being applied, or the <code>ValidateEntity</code> method is not being called. I should mention that it works correctly if I use the actual context in the web app.</p>
  
  <p>I've included some of my relevant unit testing, DbContext, and Service code below.</p>
  
  <p>Am I doing something incorrectly? Are there any known issues or workarounds? </p>
  
  <p><strong>Role DB Map</strong></p>
  
  <pre><code>public class RoleMap : EntityTypeConfiguration&lt;Role&gt;
  {
      public RoleMap()
      {
          ToTable("bm_Roles");
          HasKey(r =&gt; r.Id);
          Property(r =&gt; r.Name).IsRequired().HasMaxLength(100).HasIndex(new IndexAttribute("UX_Role_Name") { IsUnique = true });
          Property(r =&gt; r.Description).HasMaxLength(500);
      }
  }
  </code></pre>
  
  <p><strong>DbContext</strong></p>
  
  <pre><code>public class BlueMoonContext : DbContext, IBlueMoonContext
  {
      public BlueMoonContext() : base("name=BlueMoon")
      {
  
      }
  
      public DbSet&lt;Role&gt; Roles { get; set; }
      public DbSet&lt;User&gt; Users { get; set; }
  
      protected override void OnModelCreating(DbModelBuilder modelBuilder)
      {
          base.OnModelCreating(modelBuilder);
          modelBuilder.Configurations.AddFromAssembly(typeof(BlueMoonContext).Assembly);
      }
  
      public void MarkAsModified&lt;T&gt;(T entity) where T : class
      {
          entity.ThrowIfNull("entity");
          Entry&lt;T&gt;(entity).State = EntityState.Modified;
      }
  
      protected override DbEntityValidationResult ValidateEntity(DbEntityEntry entityEntry, IDictionary&lt;object, object&gt; items)
      {
          var result = base.ValidateEntity(entityEntry, items);
  
          if (entityEntry.State == EntityState.Added || entityEntry.State == EntityState.Modified)
          {
              // Perform validations that require database lookups
              if (entityEntry.Entity is Role)
              {
                  ValidateRole((Role)entityEntry.Entity, result);
              }
              else if (entityEntry.Entity is User)
              {
                  ValidateUser((User)entityEntry.Entity, result);                    
              }
          }
  
          return result;
      }
  
      private void ValidateRole(Role role, DbEntityValidationResult result)
      {
          if (role.Name.HasValue() &amp;&amp; !Roles.NameAvailable(role.Name, role.Id))
          {
              result.ValidationErrors.Add(new DbValidationError("Name", "Already in use"));
          }
      }
  
      private void ValidateUser(User user, DbEntityValidationResult result)
      {
          if (user.UserName.HasValue() &amp;&amp; !Users.UserNameAvailable(user.UserName, user.Id))
          {
              result.ValidationErrors.Add(new DbValidationError("UserName", "Already in use"));
          }
          if (user.Email.HasValue() &amp;&amp; !Users.UserNameAvailable(user.UserName, user.Id))
          {
              result.ValidationErrors.Add(new DbValidationError("Email", "Already in use"));
          }
      }
  }
  </code></pre>
  
  <p><strong>Account Service</strong></p>
  
  <pre><code>public class AccountService : BaseService, IAccountService
  {
      private IPasswordHasher _passwordHasher;
  
      public AccountService(IBlueMoonContext context, IPasswordHasher passwordHasher) : base(context)
      {
          _passwordHasher = passwordHasher;
      }
  
      public ServiceResult CreateRole(Role role)
      {
          role.ThrowIfNull("role");
          Context.Roles.Add(role);
          return Save();
      }
  
      // Copied from base service class
      protected ServiceResult Save()
      {
          var result = new ServiceResult();
          try
          {
              Context.SaveChanges();
          }
          catch (DbEntityValidationException validationException)
          {
  
              foreach (var validationError in validationException.EntityValidationErrors)
              {
                  foreach (var error in validationError.ValidationErrors)
                  {
                      result.AddError(error.ErrorMessage, error.PropertyName);
                  }
              }
          }
          return result;
      }
  }
  </code></pre>
  
  <p><strong>Unit Test</strong></p>
  
  <pre><code>[TestFixture]
  public class AccountServiceTests : BaseTest
  {
      protected Mock&lt;MockBlueMoonContext&gt; _context;
      private IAccountService _accountService;
  
      [TestFixtureSetUp]
      public void Setup()
      {
          _context = new Mock&lt;BlueMoonContext&gt;();
  
          var data = new List&lt;Role&gt;
          {
              new Role { Id = 1, Name = "Super Admin" },
              new Role { Id = 2, Name = "Catalog Admin" },
              new Role { Id = 3, Name = "Order Admin" }
          }.AsQueryable();
  
          var roleSet = CreateMockSet&lt;Role&gt;(data);
          roleSet.Setup(m =&gt; m.Find(It.IsAny&lt;object[]&gt;())).Returns&lt;object[]&gt;(ids =&gt; data.FirstOrDefault(d =&gt; d.Id == (int)ids[0]));
  
          _context.Setup(m =&gt; m.Roles).Returns(roleSet.Object);
          // _context.Setup(m =&gt; m.SaveChanges()).Returns(0);
          _accountService = new AccountService(_context.Object, new CryptoPasswordHasher());
      }
  
      [Test]
      public void AddRole_Fails_For_Empty_Name()
      {
          var role = new Role { Id = 4, Name = "" };
  
          var result = _accountService.CreateRole(role);
          Assert.False(result.Success);
      }
  }
  </code></pre>