I'm trying to fill the In-Memory database with 3 data objects. I'm using a fixture for that purpose.
My Fixture :
public class UBSeedDataFixture : IDisposable
{
public AzDbContext DBContext { get; private set; }
public UBSeedDataFixture()
{
var options = new DbContextOptionsBuilder<AzDbContext>()
.UseInMemoryDatabase(databaseName: "InMemoryTestDb")
.Options;
DBContext = new AzDbContext(options);
DBContext.UBs.Add(new UB { Title = "UB1", Code = "SomeCode" });
DBContext.UBs.Add(new UB { Title = "UB2", Code = "SomeCode" });
DBContext.UBs.Add(new UB { Title = "UB3", Code = "SomeCode" });
DBContext.SaveChanges();
}
public void Dispose()
{
DBContext.Database.EnsureDeleted();
DBContext.Dispose();
}
}
then I run two simple tests:
public class UBTests : IClassFixture<UBSeedDataFixture>
{
UBSeedDataFixture fixture;
public UBTests(UBSeedDataFixture fixture)
{
this.fixture = fixture;
}
[Fact]
public void DeleteTest()
{
var result = fixture.DBContext.UBs.SingleOrDefault(u => u.Title == "UB1");
fixture.DBContext.Remove(result);
fixture.DBContext.SaveChanges();
result = fixture.DBContext.UBs.SingleOrDefault(u => u.Title == "UB1");
Assert.Equal(null, result);
}
[Fact]
public void AddTest()
{
var ubs = fixture.DBContext.UBs.ToList();
Assert.Equal("UB1", ubs[0].Title);
}
}
As the result, I get an error that I get more than one result when I query data with Title == "UB1". If I debug my tests I have 6 elements in my database, when my fixture is supposed to create only 3. It seems like my fixture runs every time when a new test runs. How can I fix it so I have a fixture something like "Once before all tests"?
Related
I've got a setup like this with a concrete class that is instantiated inside the method I want to test. I want to mock this concrete class an not have it execute the code inside. Hence, no exception should be thrown:
public class Executor
{
public bool ExecuteAction(ActionRequest request)
{
switch (request.ActionType)
{
case ActionType.Foo:
var a = new Foo();
return a.Execute(request);
case ActionType.Bar:
var b = new Bar();
return b.Execute(request);
}
return true;
}
}
public class Foo
{
public virtual bool Execute(ActionRequest request)
{
throw new NotImplementedException();
}
}
public class Bar
{
public virtual bool Execute(ActionRequest request)
{
throw new NotImplementedException();
}
}
My NUnit test looks like this:
[Test]
public void GivenARequestToFooShouldExecuteFoo()
{
var action = new Mock<Foo>();
action.Setup(x => x.Execute(It.IsAny<ActionRequest>())).Returns(true);
var sut = new Mock<Executor>();
sut.Object.ExecuteAction(new ActionRequest
{
ActionType = ActionType.Foo
});
}
[Test]
public void GivenARequestToBarShouldExecuteBar()
{
var action = new Mock<Bar>();
action.Setup(x => x.Execute(It.IsAny<ActionRequest>())).Returns(true);
var sut = new Mock<Executor>();
sut.Object.ExecuteAction(new ActionRequest
{
ActionType = ActionType.Bar
});
}
I fiddled around with CallBase, but it didn't get me anywhere. Is there anyway I can solve this easily without dependency injection of these classes and adding interfaces? Is this possible just using Moq?
The only thing I can think to do currently is move the Execute methods into the Executor class and rename them to ExecuteFoo() and ExecuteBar(), but I have a lot of code to move so they'd have to be partial classes (sub classes?).
The problem is not with the mocking of the method but with the creation of the concrete class. The creation of Foo and Bar need to be inverted out of the Executor. It is responsible for executing the action, not creating it. with that this interface was created to handle the creation.
public interface IActionCollection : IDictionary<ActionType, Func<IExecute>> {
}
think of this as a collection of factories or a collection of creation strategies.
A common interface was created for the actions.
public interface IExecute {
bool Execute(ActionRequest request);
}
public class Foo : IExecute {
public virtual bool Execute(ActionRequest request) {
throw new NotImplementedException();
}
}
public class Bar : IExecute {
public virtual bool Execute(ActionRequest request) {
throw new NotImplementedException();
}
}
And the Executor was refactored to use dependency inversion.
public class Executor {
readonly IActionCollection factories;
public Executor(IActionCollection factories) {
this.factories = factories;
}
public bool ExecuteAction(ActionRequest request) {
if (factories.ContainsKey(request.ActionType)) {
var action = factories[request.ActionType]();
return action.Execute(request);
}
return false;
}
}
With that refactor done the Executor can be tested with fake actions.
public void GivenARequestToFooShouldExecuteFoo() {
//Arrange
var expected = true;
var key = ActionType.Foo;
var action = new Mock<Foo>();
action.Setup(x => x.Execute(It.IsAny<ActionRequest>())).Returns(expected);
var actions = new Mock<IActionCollection>();
actions.Setup(_ => _[key]).Returns(() => { return () => action.Object; });
actions.Setup(_ => _.ContainsKey(key)).Returns(true);
var sut = new Executor(actions.Object);
var request = new ActionRequest {
ActionType = ActionType.Foo
};
//Act
var actual = sut.ExecuteAction(request);
//Assert
Assert.AreEqual(expected, actual);
}
A production implementation of the factory collection can look like this
public class ActionCollection : Dictionary<ActionType, Func<IExecute>>, IActionCollection {
public ActionCollection()
: base() {
}
}
and configured accordingly with your concrete types.
var factories = ActionCollection();
factories[ActionType.Foo] = () => new Foo();
factories[ActionType.Bar] = () => new Bar();
I have the following setup:
DbContext:
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public virtual DbSet<Album> Album { get; set; }
public ApplicationDbContext()
: base("DefaultConnection", throwIfV1Schema: false)
{
}
public static ApplicationDbContext Create()
{
return new ApplicationDbContext();
}
}
Model:
public class Album
{
public int AlbumID { get; set; }
[StringLength(150)]
public string Title { get; set; }
}
Controller:
public class AlbumController : Controller
{
ApplicationDbContext db = new ApplicationDbContext();
public AlbumController(ApplicationDbContext injectDb)
{
db = injectDb;
}
// POST: Albums/Delete/5
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
[Authorize(Roles = "Admin")]
public ActionResult DeleteConfirmed(int id)
{
Album album = db.Album.Find(id);
db.Album.Remove(album);
db.SaveChanges();
return RedirectToAction("Index");
}
}
I wrote the unit test using Moq and xUnit to check DeleteConfirmed functionality:
public class AlbumsControllerTests
{
public static Mock<DbSet<T>> MockDbSet<T>(List<T> inputDbSetContent) where T : class
{
var DbSetContent = inputDbSetContent.AsQueryable();
var dbSet = new Mock<DbSet<T>>();
dbSet.As<IQueryable<T>>().Setup(m => m.Provider).Returns(DbSetContent.Provider);
dbSet.As<IQueryable<T>>().Setup(m => m.Expression).Returns(DbSetContent.Expression);
dbSet.As<IQueryable<T>>().Setup(m => m.ElementType).Returns(DbSetContent.ElementType);
dbSet.As<IQueryable<T>>().Setup(m => m.GetEnumerator()).Returns(() => inputDbSetContent.GetEnumerator());
dbSet.Setup(m => m.Add(It.IsAny<T>())).Callback<T>((s) => inputDbSetContent.Add(s));
dbSet.Setup(m => m.Remove(It.IsAny<T>())).Callback<T>((s) => inputDbSetContent.Remove(s));
return dbSet;
}
[Fact]
public void DeleteConfirmedTest()
{
// Arrange
var mockAlbumSet = MockDbSet(new List<Album> { });
Mock<ApplicationDbContext> sutDbContext = new Mock<ApplicationDbContext>() { CallBase = true };
sutDbContext.Setup(m => m.Album).Returns(mockAlbumSet.Object);
// Check if Album.Remove works inside this test
var albumToBeDeleted = new Album() { AlbumID = 1, Title = "TestAlbumName" };
sutDbContext.Object.Album.Add(albumToBeDeleted);
Assert.Equal(1, (from a in sutDbContext.Object.Album select a).Count());
sutDbContext.Object.Album.Remove(albumToBeDeleted);
Assert.Equal(0, (from a in sutDbContext.Object.Album select a).Count());
// Actual Test
sutDbContext.Object.Album.Add(albumToBeDeleted);
sutDbContext.Setup(m => m.Album.Find(It.IsAny<int>()))
.Returns(albumToBeDeleted);
AlbumController sut = new AlbumController(sutDbContext.Object);
var output = sut.DeleteConfirmed(1); // Throws NotImplementedException
// Assert
Assert.Equal(0, (from a in sutDbContext.Object.Album select a).Count());
}
}
The test throws the following exception on db.Album.Remove(album) in DeleteConfirmed:
System.NotImplementedException : The member 'Remove' has not been
implemented on type 'DbSet1Proxy' which inherits from 'DbSet1'. Test
doubles for 'DbSet`1' must provide implementations of methods and
properties that are used.
As you can see in MockDbSet method body, I setup Remove method for my Mock and it works just fine inside the unit test. Can you explain me why it doesn't work inside the controller?
Your test will work fine if you change your line:
sutDbContext.Setup(m => m.Album.Find(It.IsAny<int>()))
.Returns(albumToBeDeleted);
To:
mockAlbumSet.Setup(x=>x.Find(It.IsAny<int>()))
.Returns(albumToBeDeleted);
You made a setup for your sutDbContext to return mockAlbumSet.Object when sutDbContext.Album is called, but that line overridden your setup to create a new mock object for sutDbContext.Album property and created a single setup for that mock:
m.Album.Find(It.IsAny<int>()))
.Returns(albumToBeDeleted);
Here is a simple test, that shows you that calling setup for nested property of the class, that was previously setup to return a Mock.Object, will override that property with a new Mock.Object:
public interface IParentService
{
IDependantService Dependant { get; }
}
public interface IDependantService
{
void Execute();
}
[Fact]
//This test passes
public void VerifyThatNestedMockSetupGeneratesNewMockObject()
{
var value = 0;
var parentServiceMock = new Mock<IParentService>();
var dependantServiceMock = new Mock<IDependantService>();
dependantServiceMock.Setup(x => x.Execute()).Callback(() => { value = 1; });
parentServiceMock.Setup(x => x.Dependant).Returns(dependantServiceMock.Object);
Assert.Same(parentServiceMock.Object.Dependant, dependantServiceMock.Object);
parentServiceMock.Setup(x => x.Dependant.Execute()).Callback(() => { value = 2; });
Assert.NotSame(parentServiceMock.Object.Dependant, dependantServiceMock.Object);
parentServiceMock.Object.Dependant.Execute();
Assert.Equal(2, value);
}
I want to ask what is a good unit test for the method below GetMeetingsByInterimIdentifier where interim identifier is a string -- such as 78th2015.
We are setup to use the interface IMeetingsService. We are using MOQ and Microsoft.VisualStudio.TestTools.UnitTesting.
public class MeetingsService : IMeetingsService
{
private readonly IInterimCommitteeDbContext _db;
public MeetingsService(IInterimCommitteeDbContext db)
{
this._db = db;
}
public IQueryable<Meeting> GetMeetingsByInterimIdentifier(string interimIdentifier)
{
return
from m in this._db.Meetings
join c in this._db.Committees on m.CommitteeId equals c.CommitteeId
where c.InterimIdentifier == interimIdentifier
select m;
}
public Meeting GetMeeting(int meetingKey)
{
return this._db.Meetings.FirstOrDefault(x => x.MeetingId == meetingKey);
}
}
Edit:
But I am not sure how to set it up. This result is not null, but what does it do for me?
[TestMethod]
public void GetMeetingsByInterimIdentifier_WithInterimIdentifier_ReturnsMeetingList()
{
//Arrange
var interim = Properties.Settings.Default.DefaultInterimIdentifier;
var result = _meetingServiceMock.Setup(x => x.GetMeetingsByInterimIdentifier(interim));
//Act
//Assert
Assert.IsNotNull(result);
}
Create a Mock<IInterimCommitteeDbContext> and pass it into the constructor. On this object setup the Meetings and Committees properties to return various collections.
You should have different tests setup that return different collections. For example, how should this behave if both the Meetings and Committees are empty, i.e. there is no data in the database? How should it behave if there isn't an object with the provided InterimIdentifier? What about if there is one that matches etc.
I figured out how to do this using test doubles. I am using Entity Framework 6 with the code first model. I created a DbContext that inherited from my I-DbContext interface. Then I was able to create in-memory data to use in my service layer unit tests. Below is an example of:
the test data context,
the test dbset,
an example unit test.
This solution was available from an msdn article here:
https://msdn.microsoft.com/en-us/data/dn314429.aspx
...
public class CommitteeContextTest : ICommitteeDbContext
{
public CommitteeContextTest()
{
this.Committees = new TestDbSet();
this.CommitteeMembers = new TestDbSet();
}
public Database Database { get; }
public DbSet Committees { get; set; }
public DbSet CommitteeMembers { get; set; }
}
}
public class TestDbSet : DbSet, IQueryable, IEnumerable, IDbAsyncEnumerable
where TEntity : class
{
ObservableCollection _data;
IQueryable _query;
public TestDbSet()
{
_data = new ObservableCollection();
_query = _data.AsQueryable();
}
public override TEntity Add(TEntity item)
{
_data.Add(item);
return item;
}
public override TEntity Remove(TEntity item)
{
_data.Remove(item);
return item;
}
public override TEntity Attach(TEntity item)
{
_data.Add(item);
return item;
}
public override TEntity Create()
{
return Activator.CreateInstance();
}
}
[TestClass]
public class CommitteeServiceTest
{
private InterimCommitteeContextTest _interimCommitteeContext;
private ICommitteeService _service;
private string _interim;
[TestInitialize]
public void SetUp()
{
_interimCommitteeContext = new InterimCommitteeContextTest();
_service = new CommitteeService(_interimCommitteeContext);
_interim = Settings.Default.DefaultInterimIdentifier;
}
[TestCleanup]
public void Teardown()
{
_interimCommitteeContext = null;
_service = null;
}
[TestMethod]
public void GetCommittee_ProvideInterimCommitteeId_ReturnOneCommittee()
{
//Arrange
AddCommittees();
//Act and Assert
var result = _service.GetCommittee(_interim, 1);
Assert.AreEqual(1, result.CommitteeId); //Passes. IsActive set to true;
result = _service.GetCommittee(_interim, 0);
Assert.IsNull(result); //Fails. No committeeId = 0;
result = _service.GetCommittee(_interim, 2);
Assert.IsNull(result); //Fails. CommitteeId = 2 is not active.
}
[TestMethod]
public void AddCommittees()
{
_interimCommitteeContext.Committees.Add(new Committee() { CommitteeId = 1, InterimIdentifier = _interim, IsActive = true, CommitteeTypeId = 1 });
_interimCommitteeContext.Committees.Add(new Committee() { CommitteeId = 2, InterimIdentifier = _interim, IsActive = false, CommitteeTypeId = 1 });
_interimCommitteeContext.Committees.Add(new Committee() { CommitteeId = 3, InterimIdentifier = _interim, IsActive = true, CommitteeTypeId = 1 });
}
}
Use Mocking, that's what it is for. Use JMock or Mockito or any other library you prefer.
This is my Domain class
public partial class Department
{
public int DepartmentId { get; set; }
[Required]
public string DepartmentCode { get; set; }
[Required]
public string DepartmentFullName { get; set; }
public bool Status { get; set; }
public System.DateTime CreatedOn { get; set; }
}
In my MVC application, this is how my DepartmentService class looks like.
public class DepartmentService : IDepartmentService
{
private IUnitOfWork _UoW;
private IRepository<Department> repository;
public DepartmentService(IUnitOfWork UoW)
{
_UoW = UoW;
repository = _UoW.GetRepository<Department>();
}
public IList<Department> GetAllDepartments()
{
return repository.GetAll();
}
public bool SaveDepartment(Department newDepartment)
{
try
{
repository.Add(newDepartment);
_UoW.Save();
}
catch (Exception)
{
throw;
}
return true;
}
}
I wrote one unit test for GetAllDepartments methods as below.
[Test]
public void When_GetAllDepartments_Is_Called_RepositoryGetAll_ShouldBeCalled()
{
// Arrange
var mockUnitOfWork = new Mock<IUnitOfWork>();
var mockRepository = new Mock<IRepository<Department>>();
mockUnitOfWork.Setup(x => x.GetRepository<Department>())
.Returns(mockRepository.Object);
var sut = new DepartmentService(mockUnitOfWork.Object);
// Act
sut.GetAllDepartments();
// Assert
mockRepository.Verify(x => x.GetAll());
}
I want to test the SaveDepartment method where, when department is saved successfully, it should return true. I am not able to write unit test for this.
I also want to test when DepartmentCode or DepartmentFullName is blank and if Save is attempted, an exception should be thrown.
This is what i have so far.
[Test]
public void ShouldSucessfully_SaveNewDepartment()
{
// Arrange
var mockUnitOfWork = new Mock<IUnitOfWork>();
var mockRepository = new Mock<IRepository<Department>>();
Department newDept = new Department {
CreatedOn = DateTime.Now,
Status = true,
DepartmentFullName = "DFN",
DepartmentCode = "DC" };
mockUnitOfWork.Setup(x => x.GetRepository<Department>())
.Returns(mockRepository.Object);
var sut = new DepartmentService(mockUnitOfWork.Object);
// Act
sut.SaveDepartment(newDept);
// Assert
// ???
}
First of all - move all common arrange code to SetUp method:
private Mock<IUnitOfWork> mockUnitOfWork;
private Mock<IRepository<Department>> mockRepository;
private DepartmentService sut;
[SetUp]
public void SetUp()
{
mockUnitOfWork = new Mock<IUnitOfWork>();
mockRepository = new Mock<IRepository<Department>>();
mockUnitOfWork.Setup(x => x.GetRepository<Department>())
.Returns(mockRepository.Object);
sut = new DepartmentService(mockUnitOfWork.Object);
}
// tests will be here
That will make tests much easier to read and maintain. Next - do not stick to implementation when naming your tests:
When_GetAllDepartments_Is_Called_RepositoryGetAll_ShouldBeCalled
What if you will rename repository method to FindAll? What if service method will be renamed? Test becomes obsolete. And nobody will know about that. You should describe WHAT your SUT should do instead of HOW:
[Test]
public void ShouldGetAllDepartments()
{
var expected = new List<Department>{ CreateDepartment(), CreateDepartment()};
mockRepository.Setup(r => r.GetAll()).Returns(expected);
var actual = sut.GetAllDepartments();
Assert.That(actual, Is.EqualTo(expected));
mockRepository.VerifyAll();
}
As you can see, test name changed. Also I verify different things here - not only repository was called (that check can be removed actually), but that service returns exactly same departments which it gets from repository. Thats what service does. And second test:
[Test]
public void ShouldSucessfullySaveNewDepartment()
{
var department = CreateDepartment();
mockRepository.Setup(r => r.Add(department));
var result = sut.SaveDepartment(department);
Assert.True(result);
mockRepository.VerifyAll();
mockUnitOfWork.Verify(u => u.Save());
}
It verifies following service behavior: service should pass to repository exactly same department instance which was passed to service, and it should return true, it also calls save on unit of work to submit data.
BTW As you can see above I use helper method to make tests more clean:
private Department CreateDepartment()
{
return new Department {
CreatedOn = DateTime.Now,
Status = true,
DepartmentFullName = "DFN",
DepartmentCode = "DC"
};
}
And bonus - verifying that service does not saves department which already exists:
[Test]
public void ShouldNotSaveExistingDepartment()
{
mockUnitOfWork.Setup(u => u.Save()).Throws<NonUniqueEntityException>();
var result = sut.SaveDepartment(CreateDepartment());
Assert.False(result);
mockUnitOfWork.VerifyAll();
}
As you can see, expected behavior is simple - when unit of work throws NonUniqueEntityException during department saving, service should return false. Yes, I think it's better to return false. Here is service code which makes this test pass:
public bool SaveDepartment(Department department)
{
try
{
repository.Add(department);
_UoW.Save();
return true;
}
catch (NonUniqueEntityException e)
{
// log exception
return false;
}
}
First of all remove the redundant try...catch.
There's no point in catching an exception just to rethrow it.
As far as the test you asked for here is the snippet:
[Test]
public void ShouldSucessfully_SaveNewDepartment()
{
// Arrange
var mockUnitOfWork = new Mock<IUnitOfWork>();
var mockRepository = new Mock<IRepository<Department>>();
Department newDept = new Department { CreatedOn = DateTime.Now, Status = true, DepartmentFullName = "DFN", DepartmentCode = "DC" };
mockUnitOfWork.Setup(x => x.GetRepository<Department>()).Returns(mockRepository.Object);
var sut = new DepartmentService(mockUnitOfWork.Object);
// Act
bool result = sut.SaveDepartment(newDept);
// Assert
Assert.That(result, Is.True);
}
[Test]
public void ShouldThrowExceptionWhenExceptionThrownInternally_SaveNewDepartment()
{
// Arrange
var mockUnitOfWork = new Mock<IUnitOfWork>();
var mockRepository = new Mock<IRepository<Department>>();
mockUnitOfWork.Setup(x => x.GetRepository<Department>()).Returns(mockRepository.Object);
mockUnitOfWork.Setup(uow => uow.Save()).Throws<Exception>();
var sut = new DepartmentService(mockUnitOfWork.Object);
// Act
TestDelegate action = () => sut.SaveDepartment(new Department());
// Assert
Assert.Throws<Exception>(action);
}
I also want to test when DepartmentCode or DepartmentFullName is blank and if Save is attempted, an exception should be thrown.
It depend on who you expect to check for those values: if you want to rely on you database or unitofwork to check for those fields this is not the fixture to test for specific failure conditions it you want a unit test. Here you should only test what happens in case uow throws exception.
If you plan to add those check in the department service than you can do the following:
[Test]
public void ShouldThrowExceptionWhenDepartmentCodeIsNull_SaveNewDepartment()
{
// Arrange
var mockUnitOfWork = new Mock<IUnitOfWork>();
Department newDept = new Department
{
CreatedOn = DateTime.Now,
Status = true, DepartmentFullName = "DFN",
DepartmentCode = null
};
var sut = new DepartmentService(mockUnitOfWork.Object);
// Act
TestDelegate action = () => sut.SaveDepartment(newDept);
// Assert
Assert.Throws<ArgumentException>(action);
}
provided that you modified your method as follows:
public bool SaveDepartment(Department newDepartment)
{
if (string.IsNullOrEmpty(newDepartment.DepartmentCode))
{
throw new ArgumentException("DepartmentCode must be not null");
}
repository.Add(newDepartment);
_UoW.Save();
return true;
}
Someone shoot me as I can't see what I'm missing but the inner property of my stubbed object is null which is breaking my tests.
Many Thanks,
James
CommandService
public void Create()
{
var risk = _queryService.GetRisk(creatable.HeaderId);
if(risk.HeaderId != null) // HeaderId IS NULL??
{
...
}
}
QueryService
public Risk GetRisk(int headerId)
{
return _repository.GetRisk(headerId);
}
Unit test
[TestInitialize]
public void SetUp()
{
_mockRepository = new MockRepository();
_queryService = _mockRepository.Stub<IQueryService>();
_commandService = new CoreCommandService(_queryService);
}
public void MyTest()
{
var runRisk = new RunRisk { HeaderId = 10 };
_queryService.Stub(x => x.GetRisk(199)).Repeat.Any().Return(runRisk);
var result = _commandService.Create();
}
need to use the following to fix it.
MockRepository.GenerateMock<IQueryService>();