I'm using entity framework and trying to unit test my data services which are using EF. I'm not using repository and unit of work patterns. I tried the following approach to mock the context and DbSet:
private static Mock<IEFModel> context;
private static Mock<IDbSet<CountryCode>> idbSet;
[ClassInitialize]
public static void Initialize(TestContext testContext)
{
context = new Mock<IEFModel>();
idbSet = new Mock<IDbSet<CountryCode>>();
context.Setup(c => c.CountryCodes).Returns(idbSet.Object);
}
I get null "Object reference not set to an instance of an object" error for idbSet "Local". Is there any way to mock idbSet like this? Thanks
I worked it out like this: Created two classes named DbSetMock:
public class DbSetMock<T> : IDbSet<T>
where T : class
{
#region Fields
/// <summary>The _container.</summary>
private readonly IList<T> _container = new List<T>();
#endregion
#region Public Properties
/// <summary>Gets the element type.</summary>
public Type ElementType
{
get
{
return typeof(T);
}
}
/// <summary>Gets the expression.</summary>
public Expression Expression
{
get
{
return this._container.AsQueryable().Expression;
}
}
/// <summary>Gets the local.</summary>
public ObservableCollection<T> Local
{
get
{
return new ObservableCollection<T>(this._container);
}
}
/// <summary>Gets the provider.</summary>
public IQueryProvider Provider
{
get
{
return this._container.AsQueryable().Provider;
}
}
#endregion
#region Public Methods and Operators
/// <summary>The add.</summary>
/// <param name="entity">The entity.</param>
/// <returns>The <see cref="T"/>.</returns>
public T Add(T entity)
{
this._container.Add(entity);
return entity;
}
/// <summary>The attach.</summary>
/// <param name="entity">The entity.</param>
/// <returns>The <see cref="T"/>.</returns>
public T Attach(T entity)
{
this._container.Add(entity);
return entity;
}
/// <summary>The create.</summary>
/// <typeparam name="TDerivedEntity"></typeparam>
/// <returns>The <see cref="TDerivedEntity"/>.</returns>
/// <exception cref="NotImplementedException"></exception>
public TDerivedEntity Create<TDerivedEntity>() where TDerivedEntity : class, T
{
throw new NotImplementedException();
}
/// <summary>The create.</summary>
/// <returns>The <see cref="T"/>.</returns>
/// <exception cref="NotImplementedException"></exception>
public T Create()
{
throw new NotImplementedException();
}
/// <summary>The find.</summary>
/// <param name="keyValues">The key values.</param>
/// <returns>The <see cref="T"/>.</returns>
/// <exception cref="NotImplementedException"></exception>
public T Find(params object[] keyValues)
{
throw new NotImplementedException();
}
/// <summary>The get enumerator.</summary>
/// <returns>The <see cref="IEnumerator"/>.</returns>
public IEnumerator<T> GetEnumerator()
{
return this._container.GetEnumerator();
}
/// <summary>The remove.</summary>
/// <param name="entity">The entity.</param>
/// <returns>The <see cref="T"/>.</returns>
public T Remove(T entity)
{
this._container.Remove(entity);
return entity;
}
#endregion
#region Explicit Interface Methods
/// <summary>The get enumerator.</summary>
/// <returns>The <see cref="IEnumerator"/>.</returns>
IEnumerator IEnumerable.GetEnumerator()
{
return this._container.GetEnumerator();
}
#endregion
}
and EFModelMock:
public class EFModelMock : IEFModel
{
#region Fields
/// <summary>The country codes.</summary>
private IDbSet<CountryCode> countryCodes;
#endregion
#region Public Properties
/// <summary>Gets the country codes.</summary>
public IDbSet<CountryCode> CountryCodes
{
get
{
this.CreateCountryCodes();
return this.countryCodes;
}
}
#endregion
#region Public Methods and Operators
/// <summary>The commit.</summary>
/// <exception cref="NotImplementedException"></exception>
public void Commit()
{
throw new NotImplementedException();
}
/// <summary>The set.</summary>
/// <typeparam name="T"></typeparam>
/// <returns>The <see cref="IDbSet"/>.</returns>
/// <exception cref="NotImplementedException"></exception>
public IDbSet<T> Set<T>() where T : class
{
throw new NotImplementedException();
}
#endregion
#region Methods
/// <summary>The create country codes.</summary>
private void CreateCountryCodes()
{
if (this.countryCodes == null)
{
this.countryCodes = new DbSetMock<CountryCode>();
this.countryCodes.Add(
new CountryCode { CountryName = "Australia", DisplayLevel = 2, TelephoneCode = "61" });
}
}
#endregion
}
Then tested like this:
[TestClass]
public class CountryCodeServiceTest
{
#region Static Fields
/// <summary>The context.</summary>
private static IEFModel context;
#endregion
#region Public Methods and Operators
/// <summary>The initialize.</summary>
/// <param name="testContext">The test context.</param>
[ClassInitialize]
public static void Initialize(TestContext testContext)
{
context = new EFModelMock();
}
/// <summary>The country code service get country codes returns correct data.</summary>
[TestMethod]
public void CountryCodeServiceGetCountryCodesReturnsCorrectData()
{
// Arrange
var target = new CountryCodeService(context);
var countryName = "Australia";
var expected = context.CountryCodes.ToList();
// Act
var actual = target.GetCountryCodes();
// Assert
Assert.IsNotNull(actual);
Assert.AreEqual(actual.FirstOrDefault(a => a.CountryName == countryName).PhoneCode, expected.FirstOrDefault(a => a.CountryName == countryName).TelephoneCode);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With