I used test as below. I have one big method for initialize whole dbcontext (it is larger than pasted below, it is similar, but with more models and acces to each dbsets for MoQ Verify) something like fake db. Next I inject it to service and call method that using it.
Is it correct way for testing services (that using dbcontext) with unit tests? And if it is not correct, what is good way for testing services like this (maybe only write test that connect to real db)?
My Test:
[Test]
public void ExampleServiceTest()
{
var mock = InitializeMockContext();
var service = new TagsService(mock.Object);
var result = service.GetTags(2);
var expectection = 2;
Assert.AreEqual(expectection, result.Id);
}
Method that create mocked DBContext:
public Mock<MyDBContext> InitializeMockContext()
{
var mock = new Mock<MyDBContext>();
var mockDataTags = new List<Tags> {
new Tags { Id = 1, Count = 3 },
new Tags { Id = 2, Count = 2} }.AsQueryable();
var mockSet = new Mock<DbSet<Tags>>();
mockSet.As<IQueryable<Tags>>().Setup(m => m.Provider).Returns(mockDataTags.Provider);
mockSet.As<IQueryable<Tags>>().Setup(m => m.Expression).Returns(mockDataTags.Expression);
mockSet.As<IQueryable<Tags>>().Setup(m => m.ElementType).Returns(mockDataTags.ElementType);
mockSet.As<IQueryable<Tags>>().Setup(m => m.GetEnumerator()).Returns(mockDataTags.GetEnumerator());
mock.Setup(x => x.Tags).Returns(mockSet.Object);
//I have more than just one model here
return mock;
}
MyService:
public class TagsService
{
private readonly MyDBContext _ctx;
public TagsService(MyDBContext ctx)
{
_ctx = ctx;
}
public Tags GetTags(int count)
{
using (var db = _ctx)
{
return db.Tags.First(x => x.Count == count);
}
}
}
Related
I have a generic Repository with the Unit of Work pattern setup to utilize the Specification Pattern which works great but now I am trying to Unit test it and it seems my setup isn't returning anything when specifying what to return.
Repository Snippet
internal class Repository<T> : IRepository<T> where T : BaseEntity
{
protected readonly ApplicationDbContext _context;
public Repository(ApplicationDbContext context)
{
_context = context;
}
public IEnumerable<T> Find(ISpecification<T> specification = null)
{
return ApplySpecification(specification);
}
private IQueryable<T> ApplySpecification(ISpecification<T> spec)
{
return SpecificationEvaluator<T>.GetQuery(_context.Set<T>().AsQueryable(), spec);
}
}
}
Snippet of Specification
public class GetStocksForCurrentDaySpecification : BaseSpecification<Stock>
{
public GetStocksForCurrentDaySpecification() : base(x => x.DateInserted.Day == DateTime.Today.Day) { }
}
Snippet of me calling it
_unitOfWork.Repository<Stock>().Find(new GetStocksForCurrentDaySpecification());
This all works perfectly when running my code.
Here is my Unit Test where I do setup.
[Fact]
public void Job_Should_Execute()
{
var stockList = new List<Stock>();
stockList.Add(new Stock
{
Id = Guid.NewGuid(),
DateInserted = DateTime.Now,
Exchange = "ASX",
LongName = "Long Name",
MarketOpenPrice = 1.26M,
MarketPreviousClosePrice = 1.56M,
MarketPrice = 1.3M,
ShortName = "Short Name",
Symbol = "LGN"
});
var stockRepositoryMock = new Mock<IRepository<Stock>>();
stockRepositoryMock.Setup(m => m.Find(new GetStocksForCurrentDaySpecification())).Returns(stockList.ToArray());
var unitOfWorkMock = new Mock<IUnitOfWork>();
unitOfWorkMock.Setup(m => m.Repository<Stock>()).Returns(stockRepositoryMock.Object).Verifiable();
var job = new YahooStockMarketJob(new HttpClient(), unitOfWorkMock.Object, new EventPublisher(_listeners), _configuration);
job.Execute();
unitOfWorkMock.Verify();
}
When debugging, the following line returns an empty array instead of an array with one item it.
// Returns empty array
var stockRepositoryMock = new Mock<IRepository<Stock>>();
stockRepositoryMock.Setup(m => m.Find(new GetStocksForCurrentDaySpecification())).Returns(stockList.ToArray());
In your mock object you are setting up the Find method with a specific instance of GetStocksForCurrentDaySpecification. During your test you are passing a different instance of GetStocksForCurrentDaySpecification and since those are not the same it won't use that setup.
If you want your setup to work with your test you either need to use the same instance or allow any instance of the object by using It.IsAny<T>.
E.g.
// Returns empty array
var stockRepositoryMock = new Mock<IRepository<Stock>>();
stockRepositoryMock
.Setup(m => m.Find(It.IsAny<GetStocksForCurrentDaySpecification>()))
.Returns(stockList.ToArray());
I am trying to setup like this:
[Test]
public void Observatoins_Were_Returned()
{
using (var mock = AutoMock.GetLoose())
{
// Arrange
mock.Mock<IRepository<WspObservation>>()
.Setup(x => x.GetAll())
.Returns(_observations);
var sut = mock.Create<CommonServices>();
WspResponse wspResponse;
// Act
var wspObservations = sut.GetAllObservations(out wspResponse);
var expectedErrorCode = ResponseCodes.SUCCESS;
// Assert
// Assert.AreEqual(expectedErrorCode, wspResponse.ResponseCode);
}
}
but when GetAllObservations() function is called it returns null in the actual code.
In the actual code IRepository is dependency injected which is working fine.
object that is being returned looks like this.
var _observations = new List<WspObservation>();
_observations.Add(new WspObservation() { DeviceName = "Devcie One", Steps = "3000" });
_observations.Add(new WspObservation() { DeviceName = "Devcie One", Steps = "2000" });
the actual function that is being tested looks like this
public List<WspObservation> GetAllObservations(out WspResponse getAllWspObservationsResponse)
{
List<WspObservation> allWspObservations = new List<WspObservation>();
getAllWspObservationsResponse = new WspResponse();
try
{
//some other Business Logic
allWspObservations = _wspObsrep.GetAll().ToList();
//some other Business Logic
}
catch (Exception ex)
{
getAllWspObservationsResponse.ResponseCode = ResponseCodes.DatabaseGetError;
}
return allWspObservations;
}
dependency injection looks like this
private IRepository<WspObservation> _wspObsrep;
public CommonServices(IRepository<WspObservation> wspObsrep)
{
_wspObsrep = wspObsrep;
}
What is the intention of
var sut = mock.Create<CommonServices>();
Isn't it better to Create the real SUT object and inject the IRepository mock?
I would do it this way:
var repoMock = mock.Mock<IRepository<WspObservation>>()
.Setup(x => x.GetAll())
.Returns(_observations);
var sut = new CommonServices(repoMock);
I'm slowly starting to get the hang of unit-testing and mocking, but it's a slow process. I have tried unit testing this Active Directory code. The question is not strictly relevant to AD.
class ActiveDirectoryQueryer {
DirectorySearcher mSearcher;
public ActiveDirectoryQueryer() {
var searcher = new DirectorySearcher(...);
}
public void GetAllMailEntries() {
MailEntries =
mSearcher
.FindAll()
.Select(result => result.GetDirectoryEntry())
.Select(BuildNewADUser)
.ToList();
}
static ActiveDirectoryUser BuildNewADUser(DirectoryEntry pDirectoryEntry) {
return ActiveDirectoryUser.Create(
pDirectoryEntry.Guid,
(pDirectoryEntry.Properties["name"].Value ?? "").ToString(),
(pDirectoryEntry.Properties["mail"].Value ?? "").ToString()
);
}
So, I would like to unit test the GetAllMailEntries method. In order to do this using MOQ I've had to manually generate interfaces and wrappers for various .NET types, and changed many of the above references to interfaces instead (like IDirectoryEntry). Each of the IXxxx interfaces below has an associated wrapper class XxxxWrapper. In total I added at least 12 new source files just for this one test. Here's what I've ended up with for the unit test:
[TestMethod]
public void TestGetAllMailEntries() {
var mockSearcher = new Mock<IDirectorySearcher>();
var mockResultCollection = new Mock<ISearchResultCollection>();
var mockSearchResult = new Mock<ISearchResult>();
var mockDirectoryEntry = new Mock<IDirectoryEntry>();
var mockPropertyCollection = new Mock<IPropertyCollection>();
var nameMockPropertyValueCollection = new Mock<IPropertyValueCollection>();
var mailMockPropertyValueCollection = new Mock<IPropertyValueCollection>();
const string name = "SomeNameValue";
const string mailAddress = "SomeMailAddress";
nameMockPropertyValueCollection.SetupGet(pvc => pvc.Value).Returns(name);
mailMockPropertyValueCollection.SetupGet(pvc => pvc.Value).Returns(mailAddress);
mockPropertyCollection.SetupGet(pc => pc["name"]).Returns(nameMockPropertyValueCollection.Object);
mockPropertyCollection.SetupGet(pc => pc["mail"]).Returns(mailMockPropertyValueCollection.Object);
mockDirectoryEntry.SetupGet(de => de.Properties).Returns(mockPropertyCollection.Object);
mockSearchResult.Setup(sr => sr.GetDirectoryEntry()).Returns(mockDirectoryEntry.Object);
mockResultCollection.Setup(results => results.GetEnumerator()).Returns(new List<ISearchResult> { mockSearchResult.Object }.GetEnumerator());
mockSearcher.Setup(searcher => searcher.FindAll()).Returns(mockResultCollection.Object);
var queryer = new ActiveDirectoryQueryer(mockSearcher.Object);
queryer.GetAllMailEntries();
Assert.AreEqual(1, queryer.MailEntries.Count());
var entry = queryer.MailEntries.Single();
Assert.AreEqual(name, entry.Name);
Assert.AreEqual(mailAddress, entry.EmailAddress);
}
Is it normal to have this many interfaces and wrapper classes? (The wrappers are necessary since .NET types cannot otherwise implement my interfaces.)
I think my problem is mirroring the .NET structure too closely. I shouldn't wrap each and every .NET type all the way down till I get to just primitives. Rather, I should take the first opportunity to remove all dependencies as soon as I can. In this case it's with the DirectorySearcher class, and the FindAll method.
DirectorySearcher.FindAll returns a SearchResultCollection, but rather than thinking of my "wrapper" class as just an adapter to the .NET type, I should make more use of it.
Ignoring the implementation of IDisposable and other unnecessary code, my wrapper had looked like this:
public interface IDirectorySearcher : IDisposable {
ISearchResultCollection FindAll();
}
class DirectorySearcherWrapper : IDirectorySearcher {
DirectorySearcher mDirectorySearcher;
DirectorySearcherWrapper(DirectorySearcher pDirectorySearcher) {
mDirectorySearcher = pDirectorySearcher;
}
public static IDirectorySearcher Wrap(DirectorySearcher pDirectorySearcher) {
return new DirectorySearcherWrapper(pDirectorySearcher);
}
public ISearchResultCollection FindAll() {
return SearchResultCollectionWrapper.Wrap(mDirectorySearcher.FindAll());
}
}
Rather, I should take the opportunity to stop all dependencies right here. I don't have to return a .NET type or even just a wrapper to a .NET type, I can now use this interface to return whatever I want. IE: If what I want to get from the FindAll method is a bunch of ActiveDirectoryUsers, then return just that.
My code then becomes:
public interface IDirectorySearcher : IDisposable {
IEnumerable<ActiveDirectoryUser> FindAll();
}
class DirectorySearcherWrapper : IDirectorySearcher {
DirectorySearcher mDirectorySearcher;
DirectorySearcherWrapper(DirectorySearcher pDirectorySearcher) {
mDirectorySearcher = pDirectorySearcher;
}
public static IDirectorySearcher Wrap(DirectorySearcher pDirectorySearcher) {
return new DirectorySearcherWrapper(pDirectorySearcher);
}
public IEnumerable<ActiveDirectoryUser> FindAll() {
return
mDirectorySearcher
.FindAll()
.Cast<SearchResult>()
.Select(result => result.GetDirectoryEntry())
.Select(/*BuildNewADUser*/)
.ToList();
}
}
And the GetAllMailEntries method becomes simply:
public void GetAllMailEntries() {
MailEntries = mSearcher.FindAll();
}
And the unit test becomes:
[TestMethod]
public void TestGetAllMailEntries2() {
var mockSearcher = new Mock<IDirectorySearcher>();
mockSearcher
.Setup(s => s.FindAll())
.Returns(new[] {
ActiveDirectoryUser.Create(new Guid(), "Name", "EmailAddress")
});
var queryer = new ActiveDirectoryQueryer(mockSearcher.Object);
queryer.GetAllMailEntries();
Assert.AreEqual(1, queryer.MailEntries.Count());
var entry = queryer.MailEntries.Single();
Assert.AreEqual("Name", entry.Name);
Assert.AreEqual("EmailAddress", entry.EmailAddress);
}
I have a unit test which verifies that a function adds exactly one record to an Entity Framework dataset like so:
var internals = new Mock<DbSet<InternalTransaction>>();
internals.Setup(q => q.Create()).Returns(new InternalTransaction());
var mockDC = new Mock<IDataContext>();
mockDC.Setup(q => q.InternalTransactions).Returns(internals.Object);
// Removed: set up some data for my test
mockDC.Object.DoSomeFunction(data);
internals.Verify(e => e.Add(It.IsAny<InternalTransaction>()), Times.Once());
Since I have a lot of tests to do with this context, I'm trying to extract the mock stuff to a separate class, like so:
public static class DataContext_Creators
{
public static Mock<IDataContext> CreateMockContext()
{
var internals = CreateMockDataSet<InternalTransaction>();
var externals = CreateMockDataSet<ExternalTransaction>();
var mockDC = new Mock<IDataContext>();
mockDC.Setup(q => q.InternalTransactions).Returns(internals.Object);
mockDC.Setup(q => q.ExternalTransactions).Returns(externals.Object);
return mockDC;
}
private static Mock<DbSet<T>> CreateMockDataSet<T>() where T : class, new ()
{
var mockDataSet = new Mock<DbSet<T>>();
mockDataSet.Setup(q => q.Create()).Returns(new T());
// some other stuff, Provider, GetEnumerator, etc
return mockDataSet;
}
}
... and change my test to:
mockContext = Common.DataContext_Creators.CreateMockContext();
context = mockContext.Object;
// Removed: set up some data for my test
context.Object.DoSomeFunction(data);
//internals.Verify(e => e.Add(It.IsAny<InternalTransaction>()), Times.Once());
But now that I can't access "internals" anymore, how can I do the .Verify() statement? context.InternalTransactions won't work because that returns "internals.Object" (which it needs to for the method I'm testing to work).
From that object you may once again regain Mock object of it by using Mock.Get() method. Look at example:
public class Entity
{
public virtual int Id { get; set; }
public virtual int? ParentId { get; set; }
}
static void Main(string[] args)
{
Entity entity = Mock.Of<Entity>();
var mock = Mock.Get<Entity>(entity);
mock.Setup(e => e.ParentId).Returns(11);
var result = entity.ParentId;
// now result == 11
}
You could use Mock.Get method on your internals.Object
Create a new utility class with 2 properties:
Mock<IDataContext> DbContextMock
Mock<DbSet<InternalTransaction>> InternalTransMock
Have your Utility function return this new object so your test has access to both.
I have two tests. First test work correctly. Second test looks like as first test. However, I get exception, when I run the second test.
The first test:
public void GetCurrentBalance_Should_getting_rigth_balanse()
{
// Arrange
double balance = 10;
var mocks = new MockRepository();
IUnitOfWork unitOfWork = mocks.Stub<IUnitOfWork>();
unitOfWork.Stub(svc => svc.AccountRepository.Get()).Return(new List<Account> {new Account { Balance = balance }});
AccountService accountService = new AccountService(unitOfWork);
// Act
mocks.ReplayAll();
var result = accountService.GetCurrentBalance();
//Assert
Assert.AreEqual(balance, result);
}
The second test:
public void WithdrawMoney_Balance_should_decrease_when_money_been_withdrawn()
{
// Arrange
double balance = 10;
var mocks = new MockRepository();
IUnitOfWork unitOfWork = mocks.Stub<IUnitOfWork>();
unitOfWork.Stub(svc => svc.AccountRepository.Get()).Return(new List<Account> { new Account { Balance = balance } });
AccountService accountService = new AccountService(unitOfWork);
// Act
mocks.ReplayAll();
var result = accountService.WithdrawMoney(1); // this line is different
//Assert
Assert.AreEqual(balance - 1, result);
}
Part of my service:
public class AccountService : BaseService, IAccountService
{
public AccountService(IUnitOfWork unitOfWork)
: base(unitOfWork)
{
}
public double WithdrawMoney(double amountOfMoney)
{
var currentBalance = GetCurrentBalance();
if (currentBalance < amountOfMoney)
{
throw new BusinessLayerException("error!");
}
var lastAccount = GetLastAccount();
if (lastAccount == null)
{
throw new BusinessLayerException("error!");
}
lastAccount.Balance -= amountOfMoney;
unitOfWork.AccountRepository.Update(lastAccount);
unitOfWork.Save();
return lastAccount.Balance;
}
public double GetCurrentBalance()
{
var lastAccount = GetLastAccount();
if (lastAccount == null)
{
return 0;
}
return lastAccount.Balance;
}
private Account GetLastAccount()
{
var lastAccount = unitOfWork.AccountRepository.Get().FirstOrDefault();
return lastAccount;
}
}
I get the following call stack:
Rhino.Mocks.Exceptions.ExpectationViolationException : IUnitOfWork.get_AccountRepository(); Expected #1, Actual #2.
at Rhino.Mocks.MethodRecorders.UnorderedMethodRecorder.DoGetRecordedExpectation(IInvocation invocation, Object proxy, MethodInfo method, Object[] args)
at Rhino.Mocks.MethodRecorders.MethodRecorderBase.GetRecordedExpectation(IInvocation invocation, Object proxy, MethodInfo method, Object[] args)
at Rhino.Mocks.Impl.ReplayMockState.DoMethodCall(IInvocation invocation, MethodInfo method, Object[] args)
at Rhino.Mocks.Impl.ReplayMockState.MethodCall(IInvocation invocation, MethodInfo method, Object[] args)
at Rhino.Mocks.MockRepository.MethodCall(IInvocation invocation, Object proxy, MethodInfo method, Object[] args)
at Rhino.Mocks.Impl.Invocation.Actions.RegularInvocation.PerformAgainst(IInvocation invocation)
at Rhino.Mocks.Impl.RhinoInterceptor.Intercept(IInvocation invocation)
at Castle.DynamicProxy.AbstractInvocation.Proceed()
at Castle.Proxies.IUnitOfWorkProxy2936ffa6dea844258ad88f7a7e99dbc0.IUnitOfWork.get_AccountRepository()
at Service.AccountService.GetLastAccount() in AccountService.cs: line 90
at Service.AccountService.WithdrawMoney(Double amountOfMoney) in AccountService.cs: line 61
at ServiceTest.AccountServiceTest.WithdrawMoney_Balance_should_decrease_when_money_been_withdrawn() in AccountServiceTest.cs: line 48
follow below rules for Rhione mock test
for using Rhino Mocks just follow the steps as under with Mock Object:
1.Create mock by: mockrepository.CreateMock();
2.Record your expactations: in Record Block.
3.call ReplayAll to tell rhino Mocks that you are done with recording
4.MOST IMP. STEP:Call expected method here for example: mockMyRhinoImplementation.HelloRhinoMocks(“ABC”)
NOTE: Must need to pass the same arguments what you have recorded else it will again throw ExpectationViolationException.
5.Call VerifyAll();
So, the differene between both the tests are tht one method is having argument and the another does not have...try to use like below
double number = 1;
var result = accountService.WithdrawMoney(number);
I fix my problem by changing the second test. I change one line:
from:
IUnitOfWork unitOfWork = mocks.Stub<IUnitOfWork>();
to:
IUnitOfWork unitOfWork = mocks.DynamicMock<IUnitOfWork>();
But it seems to me that this is a bad solution to my problem.