How test this code with Moq and AutoMapper - c#

I have no experience on writting Unit Tests and I am starting with it.
My project has a Data Access Layer (with nhibernate) where I have repositories that are injected by an IoC container into some Services in a Business Layer. I want to write Unit Tests to test some methods on the Services (business Layer). I know it is important to have Moqs to simulate the Repositories and avoid hits over the dataBase. I would like to know how to test this method:
public bool AddNewProject(ProjectViewModel viewModel)
{
// _projectRepository is an interface: IProjectRepository, resolved by IoC container
if (_projectRepository.ExistsNumber(viewModel.Number))
{
Validation.AddError("Number", GlobalResource.DuplicatedNumber);
return false;
}
if (_projectRepository.GetTotalAvailable(viewModel.ItemId) > 0)
{
Validation.AddError("ItemId", GlobalResource.NotItemAvailable);
return false;
}
var project = Mapper.Map<Project>(viewModel);
project.Data = _projectRepository.GetData(viewModel.ItemId);
_projectRepository.Save(project);
viewModel.Id = project.Id;
return true;
}
I know I have to write at least three unit tests, one for each validation and one for success. The problem is that in the AutoMapper configuration, I have my IoC container resolving a type the AfterMap event, for sample:
config.CreateMap<ProjectViewModel, Project>()
.AfterMap((vm, p) => {
// it is necessary because nhibernate will save this relation
var cityRepository = container.Resolve<ICityRepository>();
p.City = cityRepository.Load(vm.CityId);
});
I saw in some place on the web that it is not necessary to have the IoC container in the unit test and I should Moq just the methods I need (not sure if it is correct). Should I have to define memory repositories and register them on a ioc container on the test project? I would be difficult to test because i need to rewrite all the repositories (more than 300).
Obs: It is difficult to change because there are more than 300 entities using Repository.Load to make associations on the AfterMap event on the AutoMapper.
This is my unit test:
[TestMethod]
public void Should_not_save_a_project_by_existent_number()
{
var viewModel = new ProjectViewModel();
viewModel.Code = "PJT";
viewModel.CityId = 1;
viewModel.ItemId = 1;
viewModel.Name = "This is a test";
// for the validation, I use this simulator in memory (in asp.net mvc I encapsulate the ModelState)
var validator = new MemoryValidation();
var projectMoqRepository = new Mock<IProjectRepository>();
// I will mock methods here...
var projectService = new ProjectService(projectMoqRepository.Object, validator);
// the ICityRepository is defined on the IoC, so when I call AddNewProject
// it will be resolved inside the AutoMapper context on the AfterMap event.
// it is not injected on the ProjectService ctor.
var result = projectService.AddNewProject(viewModel);
projectService.Validation["Number"].ShouldNotBeEmpty();
result.ShouldBeFalse();
}

Related

Unit test ServiceStack services in ServiceStack 3.9.71

I recently took a .Net project over which exposes DAOs from a Microsoft SQL Database via ServiceStack(3.9.71) REST API. Since I am gonna refactor some parts I want to unit test (at least) all servicestack services. For a better understanding I quickly draft how the implementation works.
Each Service contains a property of type DBService which encapsulates all database accesses of all services. Unfortunately this is a concrete class which makes it hard to mock. The DI.Container wrappes ServiceStack's IOC.
public class SomeService : Service
{
public DBService { get { return DI.Container.Resolve<DBService>(); } }
public object Get(SomeDataClass class)
{
var response = DBService.SomeServiceGet();
return response;
}
// other code omitted
}
The DBService looks like this (draft):
public class DBService
{
public IDbConnectionFactory DBFactory { get { return DI.Container.Resolve<IDbConnectionFactory>(); } }
public SomeServiceResponse SomeServiceGet()
{
//DB Access here...
// ...
}
public SomeOtherServiceResponse SomeOtherServiceGet()
{
//...
}
// following about 30 other methods for all the services (POST,GET,PUT etc)
}
I read the detailed response to this question but I was not able to create and initialize a BasicAppHost in ServiceStack 3.9.71 since it immediately threw a System.TypeLoadExceptionMethod 'get_VirtualPathProvider'.
On the other hand I was thinking that I do not actually need a BasicAppHost. I just have to unit test the DBService and then the servicestack services with a somehow mocked DBService. The only problem I have is that DBService is not an interface and that I am actually not sure how to deal (mock) with the SQL database and the IOC.
[UPDATE]
Unfortunately I am still not able to test a service since I can not just new the service in my test. If I do so I get:
System.TypeLoadExceptionCould not load type 'ServiceStack.ServiceHost.IService' from assembly
Here is my test:
[Fact]
public void SomeDataTest()
{
var serviceUnderTest = new SomeService();
var response = serviceUnderTest.Get(new SomeDataClass());
Assert.NotNull(response);
}
I guess the problem is that the services strongly uses alot of properties which are injected via the IOC. How can I mock that? Creating a BasicAppHost and retrieving the service from there also does not work which I already mentioned.
If you are just testing your service class, then you can directly mock any dependencies:
[Fact]
public void SomeDataTest(
{
var serviceUnderTest = new SomeService();
var logger = new Mock<ILogger>(); // Rhino mocks fashion.
serviceUnderTest.Logger = logger.Object;
var response = serviceUnderTest.Get(new SomeDataClass());
Assert.NotNull(response);
}
There's an page in their older docs here about integration testing in case you want to test the AppHost
Edit: there's an example of mocking the service dependencies here.

MVC3 Unit Test Controller with Property Injection

I have a MVC3 project that uses property injection. Within my controllers I make a call to a service class. As I mentioned it uses property injection (with unity) instead of resolving this through the constructor. I have searched all over trying to find an example of a unit test that resolves these dependencies within my controller but everything seems to refer to constructer DI. I’m getting frustrated. Any help would be great.
Example of Controller:
[Dependency]
public ITrainingService trainingService { get; set; }
public ActionResult Index(MyTrainingView myTrainingView)
{
//Load all training items into view object
myTrainingView.training = trainingService.getTraining(myTrainingView.trainingId);
myTrainingView.videos = trainingService.getTrainingVideos(myTrainingView.trainingId);
myTrainingView.visuals = trainingService.getTrainingVisuals(myTrainingView.trainingId);
myTrainingView.exams = trainingService.getTrainingExams(myTrainingView.trainingId);
return View(myTrainingView);
}
I'm trying to resolve the trainingService when running my unit test. I have found countless examples for mocking and resolving dependencies using constructor dependency but nothing when it comes to property injection.
You don't need to rely on unity in your unit tests.
Something like this would do the trick:
[Test]
public void GetTrainingById()
{
var mockService = MockRepository.GenerateMock<ITrainingService>();
mockService.Stub(service => service.getTraining(123)).Return(new ImaginaryClass());
var sut = new TrainingController();
sut.trainingService = mockService;
var myTrainingView = new MyTrainingView();
sut.Index(myTrainingView);
Assert.AreEqual(expected, myTrainingView.training);
}
If you must use unity in your unit tests, you could just instantiate the UnityContainer in your test and use the RegisterInstance to register the objects you want to inject.

Unit Testing and Mocking using RhinoMocks

I am trying to setup tests for my new projects and come across some difficulties.
I am using NUnit and Rhino Mocks.
The Code that I am trying to test is this,
public DocumentDto SaveDocument(DocumentDto documentDto)
{
Document document = null;
using (_documentRepository.DbContext.BeginTransaction())
{
try
{
if (documentDto.IsDirty)
{
if (documentDto.Id == 0)
{
document = CreateNewDocument(documentDto);
}
else if (documentDto.Id > 0)
{
document = ChangeExistingDocument(documentDto);
}
document = _documentRepository.SaveOrUpdate(document);
_documentRepository.DbContext.CommitChanges();
}
}
catch
{
_documentRepository.DbContext.RollbackTransaction();
throw;
}
}
return MapperFactory.GetDocumentDto(document);
}
And my testing code is as follows
[Test]
public void SaveDocumentsWithNewDocumentWillReturnTheSame()
{
//Arrange
IDocumentService documentService = new DocumentService(_ducumentMockRepository,
_identityOfSealMockRepository, _customsOfficeOfTransitMockRepository,
_accountMockRepository, _documentGuaranteeMockRepository,
_guaranteeMockRepository, _goodsPositionMockRepository);
var documentDto = new NctsDepartureNoDto();
documentDto.IsDirty = true;
documentDto.Id = 0;
//Act
var retDocumentDto = documentService.SaveDocument(documentDto);
//Assert
Assert.AreEqual(documentDto, documentDto);
}
private static IDbContext CreateMockDbContext()
{
var dbContext = MockRepository.GenerateMock<IDbContext>();
// setup expectations for DbContext mock
//dbContextMock.Expect(...)
// bind mock of the DbContext to property of repository.DbContext
_ducumentMockRepository.Expect(mock => mock.DbContext).Return(dbContext).Repeat.Any();
return dbContext;
}
I need to pass in a documentDto with say isDirty set and test if it returns the same object.
So I was thinking to use a Stub instead of a mock.
I need to to find out how to set expectations so I can test the logic on the code.
you need to mock or stub all of the components which you do not want to test. You should, as a rule of thumb only have a maximum of single mock object the rest should be stubs. Mock the things you want to verify interaction with and stub the things which you just want to provide data for your test.
you don't tell us what type your _documentRepository is so its hard to tell exactly what you are testing here, but to test this method the only thing you can do, IMHO, is check that if the IsDirty flag is set is check that the correct methods on the _documentRepository and the Context are called.
To do this I would create a mock _documentRepository and mock DbContext and set expectations that _documentRepository.SaveOrUpdate(document) is called with the document passed in. Actually looking again at the code you need to convert between the dto and the document. Currently this is being done in a method. I would create a interface and a class for this and make that interface a dependency of the class you are testing so that you can create a stub which returns a known document from the documentDto. This class could handle creating a new document or returning an existing one based on the id in the Dto. otherwise you'll have to know what type of document is returned.
something like:
var documentDto = new NctsDepartureNoDto();
documentDto.IsDirty = true;
documentDto.Id = 0;
IDbContext context = MockRepository.GenerateMock<IDbRepository>();
context.Expect(x=>x.BeginTransaction()).Return(MockRepository.GenerateStub<ITransaction>());
context.Expect(x=>x.CommitChanges());
then create a mock for the repository
IDocumentRepository repo = MockRepository.GenerateMock<IDocumentRepository>();
repo.Expect(x=>x.DbContext).Return(context).Repeat().Any();
repo.Expect(x=>x.SaveOrUpdate(Arg<Document>.Is.Any())).Return(MockRepository.GenerateStub<Document>);
This tests that you interact with the repository object correctly when the dirty flag is set. It shouldn't test that the document is saved correctly or that the correct document is returned when SaveOrUpdate is called, as this should be tested in the tests for the repository, not here.
'But wait!' I hear you cry, 'you said at the beginning that there should only be a single mock, and here we have 2!'. That's true, and I think that this shows a fault in your current design.
You should not, I don't think, be exposing the DBContext from your documentRepository. You seem to be doing so in order to use the transactions.
If your repository needs to be aware of the transactions then have methods on the repository that allow the transactions to be controlled (or hide the fact that the transactions exist inside the repository object completely). These methods might just delegate to the internal DbContext but it would then mean that the only mock would need to be the document repository object itself, and not the DbContext

Is it possible to unit test methods that rely on NHibernate Detached Criteria?

I have tried to use Moq to unit test a method on a repository that uses the DetachedCriteria class. But I come up against a problem whereby I cannot actually mock the internal Criteria object that is built inside. Is there any way to mock detached criteria?
Test Method
[Test]
[Category("UnitTest")]
public void FindByNameSuccessTest()
{
//Mock hibernate here
var sessionMock = new Mock<ISession>();
var sessionManager = new Mock<ISessionManager>();
var queryMock = new Mock<IQuery>();
var criteria = new Mock<ICriteria>();
var sessionIMock = new Mock<NHibernate.Engine.ISessionImplementor>();
var expectedRestriction = new Restriction {Id = 1, Name="Test"};
//Set up expected returns
sessionManager.Setup(m => m.OpenSession()).Returns(sessionMock.Object);
sessionMock.Setup(x => x.GetSessionImplementation()).Returns(sessionIMock.Object);
queryMock.Setup(x => x.UniqueResult<SopRestriction>()).Returns(expectedRestriction);
criteria.Setup(x => x.UniqueResult()).Returns(expectedRestriction);
//Build repository
var rep = new TestRepository(sessionManager.Object);
//Call repostitory here to get list
var returnR = rep.FindByName("Test");
Assert.That(returnR.Id == expectedRestriction.Id);
}
Repository Class
public class TestRepository
{
protected readonly ISessionManager SessionManager;
public virtual ISession Session
{
get { return SessionManager.OpenSession(); }
}
public TestRepository(ISessionManager sessionManager)
{
}
public SopRestriction FindByName(string name)
{
var criteria = DetachedCriteria.For<Restriction>().Add<Restriction>(x => x.Name == name)
return criteria.GetExecutableCriteria(Session).UniqueResult<T>();
}
}
Note I am using "NHibernate.LambdaExtensions" and "Castle.Facilities.NHibernateIntegration" here as well. Any help would be gratefully appreciated.
Essentially I am getting a null reference exception on the assert of the object returned. Thus I assume that I have not connected up the criteria correctly. But I don't think I can do this because the criteria is a private field of the Detached Criteria which is created inside my repository!
Honestly I gave up on trying to unit test anything that touches the database a long time ago.
It's so much easier to spin up an in memory Sqlite db and just run the actual tests. Or if you would rather run them against the real database then just move them into your integration tests that only get ran when you do a checkin to source control.
I think you're missing the point of using mocking in this situtation. What you want to mock is the method
public SopRestriction FindByName(string name)
{
...
}
So then you can return any type of SopRestriction you want and not worry about the fact it's querying NHibernate.
It's pointless to ever mock any type of datacontext because you'll never gain any value.
The easiest way to do this would be to extract an interface from TestRepository so like ITestRepository and then make the rest of your dependency graph dependent on ITestRepository and you can mock the repository itself easily in your unit tests.
Follow up: Regarding your response about wanting to verify method calls inside your repository what I would reccomend is wrapping all of the NHibernate specific usage into methods themselves that don't have any type of parameter or return that is NHibernate specific so then you can mock those methods and just expect them to work. This is why unit testing is less valuable at this stage because you don't gain much. With what you said I wouldn't mock them at all but would make them full "integration" tests that touch the database or do what they need to do. I still consider these to be unit tests even if TDD purists would say they're integration tests.

MEF creation policy

I am attempting to use the shared part creation policy for a MEF export. It does not, however, seem to work the way I was thinking. I do the composition twice in my application and each time get a fresh copy of the object. I've proved this by adding an instance counter to the object instanciation
static int instCount = 0;
public FakeAutocompleteRepository()
{
instCount++;
...
}
and running it all in debug. Indeed the second time I do a composition I get a new copy of the FakeAutocompleteRepository with instCount = 2. The export section contains
[PartCreationPolicy(CreationPolicy.Shared)]
[Export(typeof(IAutocompleteRepository))]
[ExportMetadata("IsTesting", "True")]
class FakeAutocompleteRepository : IAutocompleteRepository
{ ... }
Is there some trick to getting the same instance for subsiquent requests? In case it is something I'm doing during the composition this is how I'm doing that
var catalog = new AggregateCatalog();
catalog.Catalogs.Add(new AssemblyCatalog(System.Reflection.Assembly.GetExecutingAssembly()));
catalog.Catalogs.Add(new DirectoryCatalog("."));
var container = new CompositionContainer(catalog);
var batch = new CompositionBatch();
batch.AddPart(this);
container.Compose(batch);
if (null != ConfigurationSettings.AppSettings["IsTesting"] && bool.Parse(ConfigurationSettings.AppSettings["IsTesting"]))
repository = container.GetExports<IAutocompleteRepository>().Where(expDef => expDef.Metadata.Keys.Contains("IsTesting")).Single().GetExportedObject();
Basically I'm trying to force a specific composition during testing. If you have a better idea for unit testing these compositions then I'm all ears.
I don't see anything specifically in your code that would cause more than one of your part to be created. Are you creating a different container for each composition? If you are, that is why you are getting separate instances.
As far as how to combine composition and unit testing in general, there is some discussion of this here.
What I did for unit testing was avoid composition. For instance (I'm using WPF and MVVM here), let's say you want to test this ViewModel:
[Export("/MyViewModel")]
public class MyViewModel
{
[ImportingConstructor]
public MyViewModel(
[Import("/Services/LoggingService")] ILoggingService l)
{
logger = l;
}
private ILoggingService logger { get; set; }
/* ... */
}
I don't want to instantiate the full-blown logging service every time I do a unit test, so I have a MockLoggingService class that implements ILoggingService and it just swallows all the log messages, (or checks that the proper messages are being generated, if you care). Then I can do this in my unit test:
MyViewModel target = new MyViewModel(new MockLoggingService());

Categories